React组件生命周期,状态和Redux

9
我希望使用redux来存储整个react应用的状态,但是我在一个特殊情况下遇到了困难:
  • 当组件需要本地状态并由生命周期方法(如componentDidUpdatecomponentDidMount)修改时,该怎么办?

以下是包含由isotope布局库排列的“卡片”的React组件示例:

componentDidMount() {
    let container = ReactDOM.findDOMNode(this);
    if (! this.state.isotope) {
        this.setState({ isotope: new Isotope(container, {itemSelector: '.grid-item', layoutMode: 'masonry'})});
    }
}

componentDidUpdate(new_props, new_state) {
    if (new_state.items_list != this.state.items_list) {
        if (this.state.isotope) {
            this.state.isotope.reloadItems();
            this.state.isotope.layout();
            this.state.isotope.arrange();
        }
    }
}

有没有一种方法可以删除此组件中的本地状态,并改用redux?我不知道如何做到这一点。


你的items_list是如何被填充的? - David L. Walsh
我有一个函数,使用items_list进行setState。 - mguijarr
1个回答

16

将您的items_list放入redux状态中。 您的reducer可能如下所示:

const initialState = {
    items: []
};

export function myReducer(state = initialState, action) {
    switch (action.type) {
        case 'SET_ITEMS':
            return Object.assign({}, state, {
                items: action.items
            });
    }
    return state;
}

或者对于稍微复杂一些的内容:

const initialState = {
    items: []
};

export function myReducer(state = initialState, action) {
    switch (action.type) {
        case 'ADD_ITEM':
            return Object.assign({}, state, {
                items: [ ...state.items, action.item ]
            });
        case 'REMOVE_ITEM':
            return Object.assign({}, state, {
                items: [
                    ...state.items.slice(0, action.index),
                    ...state.items.slice(action.index + 1)
                ]
            });
    }
    return state;
}

一旦您配置了存储和提供程序(请参阅Redux文档),请按以下方式设置"智能组件":

function mapStateToProps(state) {
    return {
        items: state.items
    }
}

function mapDispatchToProps(dispatch) {
    const actions = bindActionCreators(actionCreators, dispatch);
    return {
        addItem: actions.addItem,
        removeItem: actions.removeItem
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(Root);

现在你的项目和操作是你的根组件的 props。如果你的项目存放在低级组件中,只需将它们作为 props 传递下去即可。

希望这能给你一个大致的想法。使用 Redux 后,您会发现您的 React 组件会少用状态而更多地用 props。

还有一件事......

这可能是一个小问题,但我敦促您不要将您的 isotope 对象存储在组件状态上。(无论您是否使用 Redux。)isotope 对象并不真正属于状态,而是您的视图。在 React 中,组件响应状态变化而更新。但是您的 componentDidUpdate 却相反:它根据组件更新来改变状态。

作为替代方案,只需将其存储在对象本身上。例如:

componentDidMount() {
    const container = ReactDOM.findDOMNode(this);
    this.isotope = new Isotope(container, {
        itemSelector: '.grid-item',
        layoutMode: 'masonry'
    });
}

componentDidUpdate(prevProps, prevState) {
    if (prevProps.items !== this.props.items) {
        this.isotope.reloadItems();
        this.isotope.layout();
        this.isotope.arrange();
    }
}

尽管通常我不建议在React中使用这种实例变量,但像 Isotope 这样的 DOM 操作库是值得例外的。


感谢您就同位素和组件状态提供的建议,确实将其存储在状态中是一个错误。还有感谢您的答案,基本上我按照您说的做了,现在很满意 :) - mguijarr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接