使用相同组件编辑和添加数据的最佳方法。将组件状态与Redux存储混合

时间:2018-12-23 19:56:39

标签: javascript reactjs redux

我正在使用Redux构建React中的Web应用程序。这是简单的设备管理器。我正在使用相同的组件在数据库中添加和更新设备。我不确定我的方法是否正确。在这里,您可以找到我的解决方案的一部分:

更新模式:

在componentDidMount中,我正在检查是否以url(编辑模式)传递了deviceId。如果是这样,我正在调用redux动作以从数据库中检索数据。我正在使用connect函数,所以当响应到达时,它将被映射到组件props。

这是我的mapStateToProps(可能我应该只映射特定的属性,但是在这种情况下没关系)

const mapStateToProps = state => ({
    ...state
})

和componentDidMount:

componentDidMount() {
    const deviceId = this.props.match.params.deviceId;
        if (deviceId) {
            this.props.getDevice(deviceId);
            this.setState({ editMode: true });
        }
    }

接下来,将触发componentWillReceiveProps,我将能够调用setState以便在表单中填充输入。

componentWillReceiveProps(nextProps) {
    if (nextProps.devices.item) {
        this.setState({
            id: nextProps.devices.item.id,
            name: nextProps.devices.item.name,
            description: nextProps.devices.item.description
        });
    }
}

添加模式:

添加模式甚至更简单-我只是在每次输入更改时调用setState。

handleChange = name => event => {
    this.setState({
        [name]: event.target.value,
    });
};

这就是我的输入的样子:

<TextField
    onChange={this.handleChange('description')}
    label="Description"
    className={classes.textField}
    value={this.state.description}
/>

我不喜欢这种方法,因为我必须在从后端接收数据后调用setState()。我也在使用componentWillReceiveProps,这是一种不好的做法。

有没有更好的方法?例如,我只能使用redux存储而不是组件状态(但是我不需要redux存储中的输入数据)。也许我可以使用React ref字段并摆脱组件状态?

其他问题-我真的应该在每个onChange输入上调用setState吗?

1 个答案:

答案 0 :(得分:0)

为避免使用componentWillReceiveProps,并且由于您正在使用redux,可以执行以下操作:

class YourComponent extends React.Component {

    state = {
        // ...
        description: undefined,
    };

    static getDerivedStateFromProps(nextProps, prevState) {
        if (prevState.description === undefined && nextProps.description) {
            return { description: nextProps.description };
        }

        return null;
    }

    componentDidMount() {
        const deviceId = this.props.match.params.deviceId;
        if (deviceId) {
            this.props.getDevice(deviceId);
            this.setState({ editMode: true });
        }
    }

    handleChange = name => event => {
        this.setState({
            [name]: event.target.value,
        });
    };

    // ...

    render() {
        let { description } = this.state;
        description = description || ''; // use this value in your `TextField`.

        // ...

        return (
            <TextField
                onChange={this.handleChange('description')}
                label="Description"
                className={classes.textField}
                value={description}
            />
        );
    }

}

const mapStateToProps = (state) => {
    let props = { ...state };
    const { devices } = state;
    if (devices && devices.item) {
        props = {
            ...props,
            id: devices.item.id,
            name: devices.item.name,
            description: devices.item.description,
        };
    }

    return props;
};

export default connect(
    mapStateToProps,
)(YourComponent);

然后您可以访问id而不是name的{​​{1}},descriptionthis.props。之所以起作用,是因为每次您更新Redux存储都会评估this.state。另外,您将能够通过mapStateToProps访问description,并保持this.state不变。您可以了解有关TextField here的更多信息。

关于第二个问题,每次输入更改时都调用getDerivedStateFromProps完全可以;这就是所谓的受控组件,React团队(也不是我)鼓励使用它。参见here