メンチカツ

ロースカツが好きです

ReactのcomponentWillReceivePropsはPropTypes.funcの呼び出しも捕捉する

はまったのでメモ

以下のようなpropsstateを持つコンポーネント

static propTypes = {
    onChange: PropTypes.func.isRequired,  // this.state.selectedItemListが変更されたときに発火
    itemList: PropTypes.array.isRequired, // DBからとってきたマスター的なデータ
};

constructor(props) {
    super(props);
    this.state = {
        selectedItemList: [] //選択状態を管理する
    };
}

this.props.itemListidnameで構成されたデータで、 そのデータにcheckboxを付与して取捨選択をさせる、というもの。 選択状態はthis.state.selectedItemListで管理する。

ちなみに、this.props.itemListには検索結果を与えるので、 変更がかかったらthis.state.selectedItemListの選択状態は 都度初期化したい。

というわけで、初期化処理をcomponentWillReceivePropsに 書いた。

componentWillReceiveProps(nextProps) {
    // this.props.itemList から選択状態を管理するthis.state.selectedItemList を生成
    var selectedItemList = [];
    nextProps.itemList.map(function (item, index) {
        selectedItemList.splice(index, 0, {
            itemId: item.id,
            checked: false, //チェック状態
        });
    });
    this.setState({
        selectedItemList: selectedItemList
    });
}

選択状態の変更時は、this.props.onChangeに最新の 選択リストを与える。

handleChange(index, checked) {
    var selectedItemList = this.state.selectedItemList;
    selectedItemList[index].checked = checked;
    this.setState({selectedItemList: selectedItemList}, this.props.onChange(selectedItemList));
}

と、this.props.onChange(selectedItemList)を コールしたところでcomponentWillReceiveProps()が走って selectedItemListが全部初期化されちゃった!orz

ので、componentWillReceivePropsを以下に書き換えた。

componentWillReceiveProps(nextProps) {
    //this.props.itemListの変更がなければbreak
    if(this.props.itemList == nextProps.itemList){
        return false;
    }
    // this.props.itemList から選択状態を管理するthis.state.selectedItemList を生成
    var selectedItemList = [];
    nextProps.itemList.map(function (item, index) {
        selectedItemList.splice(index, 0, {
            itemId: item.id,
            checked: false, //チェック状態
        });
    });
    this.setState({
        selectedItemList: selectedItemList
    });
}

問題は解消されたけれど、なんだかな。 特定のpropsだけlistenできたらいいのにな。