immutableと組み合わせてreact開発を行う

4358 ワード

なぜimmutableを使うのか
私たちが何かを使う必要があるとき、自然にこのようなものを使わないと解決しにくい問題に遭遇しました.今日reactアプリを書いていると、reduxではなくcontainerレベルのコンポーネントのstateの構造が複雑になると、リーフノードのデータを修正してsetStateを行うたびに非常に面倒になるという問題が見つかりました.例えば次のような
class Container extends Component {
  constructor() {
    super();
    this.state = {
      a: {
        aa: {
          aaa: 1
        }
      }
    };
  }
  ...
}
a.aa.aaaの値を変更するたびにsetStateを行うのは面倒です
onChnage() {
  this.setState({
    a: {
      aa: {
        aaa: 2
      }
    }
  })
}
小さな点を変更するたびに、state全体の構造を書き直す必要があります.今は無理ですが、データ構造がa,b,c,d...になると、このようなネストがあります.それとも、このように繰り返し書きますか.それは後期になると、毎日2つのsetStateを書いて、私たちは家に帰って食事をすることができます.もちろん、コードを書くのが一般的な友達もいるかもしれません.
onChange() {
  this.state.a.aa.aaa = 2;
  this.setState(this.state);
}
このやり方はもちろん望ましくありません.そして、そう書くと、reactはstateの値を直接変更できないと警告します.setStateの原理を知っていれば、setStateはすぐにUIを更新しないことがわかります.非同期更新プロセスです.setStateを呼び出すたびに、更新するstateが格納され、実行スタックの最後にマージされます.stateを直接変更すると、state全体が現在の実行スタックで非常に混乱し、stateが最初にどの方法で変更されたのか分からないため、予知できないエラーが発生しやすくなります.では、私たちはどのようにこの問題を解決しますか.付与?
var myState = this.state;
myState.aa.aaa = 2;
this.setState(myState);
いいですか.もちろんだめです.JSは参照賦値なので、stateを直接修正するのと何の違いもありません.だから、仕方がありません.深さクローンを採用するしかありません.しかし、深度クローンを使用すると、非常に深刻なパフォーマンスの問題に直面し、デルの最適な解決策ではありません.では、このときimmutableを使う必要があります.可変データ構造を構築し、現在のデータを変更するたびに、新しいデータ構造を生成します.また、immutable内部では特殊な最適化方式が採用されているため、変更されたノードのみがクローン化され、変更されていないノードが共有されるため、依然として低い性能消費を維持しており、このようにして状態の修正を行うことで、後顧の憂いがなくなります.もちろん、私が前に述べた状況はimmutableが威力を示す小さなシーンにすぎず、プロジェクトでimmutableを使用すると、より多くの予想外のメリットをもたらします.
immutableの使い方
ここではフェイスブック公式のimmutable.js,gitアドレスを使用します.https://github.com/facebook/immutable-js、ドキュメントのアドレス:http://facebook.github.io/immutable-js/docs/#/ドキュメントページf 12でコンソールを開き、apiのテストもできます.ここではよく使うapiをいくつか挙げて、自分の後の復習にも便利です.
fromJS()
これは比較的一般的な方法であり,Objectへの伝達,Mapへの伝達,Arrayへの伝達,Listへの伝達であるため,一般的なデータ変換はこれで十分である.
import {fromJS} from 'immutable';

let origin = {
  a: {
    aa: {
      aaa: 1
    }
  }
}
let imt = fromJS(orgin);
get()でデータを取得する
immutableを使用すると、以前のa.aa.aaaのようにデータを取得することはできません.get()メソッドを使用する必要があります.
let aaa = imt.get('a').get('aa').get('aaa');
update()を使用してデータを更新する
updateの最初のパラメータはkeyですが、2番目のパラメータは関数で、そのパラメータが元の値であることに注意してください.
let result = imt.get('a').get('aa').update('aaa', old => 2);
サンプルコード
immutbaleが書いた簡単なtabコンポーネントを貼り付けます
container.js
import React, {Component} from 'react';
import TopBar from './top-bar';
import Content from './content';
import {fromJS} from 'immutable';

class Container extends Component {
  constructor() {
    super();

    this.state = {
      active: 0,
      contents: fromJS(['  item1   : 11111111111111',
        '  item2   : 22222222222222',
        '  item3   : 33333333333333']),
      items: fromJS(['item1', 'item2', 'item3'])
    };

    this.changeFocus = this.changeFocus.bind(this);
  }

  changeFocus(index) {
    var state = this.state;
    state.active = index;
    this.setState(state);
  }

  render() {
    return (
      
); } } export default Container;
top-bar.js
import React from 'react';
import "./top-bar.css";

let TopBar = ({items, changeFocus}) => {

  return (
    
    {items.map(function(item, i) { return (
  • changeFocus(i)}>{item}
  • ); })}
); } export default TopBar;
content.js
import React, { Component } from 'react';

class Content extends Component {

  render() {
    let items = this.props.contents.map((item, i) => {
      return (
        
{item}
); }) return (
{items}
); } } export default Content;