首页 > 解决方案 > 如何使用 reducer 正确处理反应状态和专业人士更新

问题描述

我是 react 新手,我一直在尝试用 reactjs 制作一个设置页面。我想要实现的是,当用户第一次加载页面时,我希望从反应组件状态加载设置页面属性,因为不会有任何设置可用,当用户提交数据并且页面第二次呈现时现在应该从来自 redux-saga 的 props 加载设置属性。我已经编写了如下代码

    import React, { Component } from 'react';

    class Setting extends Component {

        constructor(props) {
            super(props)
            this.state = {
                settings_1: {},
                settings_2: {
                    child_one: {
                        subchild_one:true,
                        subchild_two:true
                    }
                }
            }
        }

        componentDidMount() {
            this.props.activateAuthLayout();
            if (this.props.user !== null && this.props.user.shop_id) {
                this.props.loadSettings({
                    payload: { ...this.props.user},
                });
            }

        }

        handleChange = (event) => {
            let data = {[event.target.name]: value= [event.target.value]};
            let newState = { ...this.state.settings_2.child_one, data };
            this.setState({settings_2: newState });
        }


        render() {

            if(!this.props.is_settings_loaded){
                return (
                    <div>loading...</div>
                )
            }

            return (
                <div className="content">
                    <div className="custom-control custom-checkbox mb-0">
                        <input
                            type="checkbox"
                            className="custom-control-input"
                            id="checkbox1"
                            name="subchild_one"
                            checked={this.props.settings.settings_2.child_one.subchild_one || this.state.settings_2.child_one.subchild_two}
                            onChange={e => this.handleChange(e)}
                        />
                        <label className="custom-control-label font-weight-normal darktextcolor" htmlFor="sync_all_product_attributes">Select All</label>
                    </div>
                </div>

            );
        }

    }

    const mapStatetoProps = state => {
        const { user } = state.Common;
        const { settings, is_settings_loaded } = state.Settings;
        return { user, settings, is_settings_loaded };
    }

    export default withRouter(connect(mapStatetoProps, { activateAuthLayout, loadSettings, updateSettings })(Setting));

一切正常,除了道具上有可用设置并且我想取消选中该复选框时,它永远不会取消选中。我发现那是因为现在我有道具并且没有改变。我该如何处理这种情况?

我尝试使用 defaultChecked 而不是选中,但我选择了所有复选框,如果我使用 defaultCheck,这将不起作用。

任何形式的建议都受到高度赞赏。谢谢

标签: reactjscheckboxstate

解决方案


关于 redux 和 react 状态

要解决的第一个问题是您将 redux 的状态镜像到 react 的状态。这是一种反模式,您应该遵循单一事实来源以避免差异。


修复你消费的状态

回想起来,你应该从你的反应状态中删除与 redux 相关的状态。然后你handleChange应该用它this.props.updateSettings来更新你的 redux 的状态。这样,您在组件中的所有数据都将正确反映。

对于您的 handleChange 逻辑,您应该使用该属性的复选框checked。此外,您似乎在数据构建和 newState 上有一些错误。您正在将您的值包装到一个数组中,并且您似乎正在分配给value未声明的变量

您应该将下一个 redux 的状态传递给您的updateSettings,例如:

handleChange = (event) => {
    let data = {[event.target.name]: event.target.checked};
    let newState = { ...this.props.settings_2.child_one, ...data };
    this.props.updateSettings(newState);
}

你的输入也name应该是subchild_one而不是child_one,你的检查应该只指向你的道具subchild_one

<input
    type="checkbox"
    className="custom-control-input"
    id="checkbox1"
    name="subchild_one"
    checked={this.props.settings_2.child_one.subchild_one}
    onChange={this.handleChange}
/>

推荐阅读