如何正确设置子组件和父组件的状态?

时间:2019-01-28 20:34:53

标签: javascript reactjs

在下面的示例中,我尝试执行以下操作:

  • 我有输入字段,我想以对{ id: value, id: value, ...etc }的形式捕获对这些输入所做的更改:onChange,然后我可以将此数据结构发送到服务以执行...无论如何:)

我在实施过程中遇到问题

  • 当输入字段更改为 Input 组件时,我需要通过setState管理class Submit extends React.Component { constructor(props) { super(props); } render() { const { showButton } = this.props; return ( <button type='button' disabled={!showButton}> Hello world! </button> ); } ); ,这在React中是很典型的。但是,我还需要捕获对输入字段所做的更改。
  • 要捕获更改,我正在使用 Parent 组件处理回调函数,该函数将使用新更改来更新状态。
  • 此外,如果存在新更改,我仅允许用户提交更改。暂时保持简单,存在新更改时启用一个按钮。

TLDR :我相信我使用set state出了点问题,我试图通过回调函数在子级和父级中设置状态。但是,一个优先于另一个,两个设置状态都没有执行。为什么会这样以及如何正确实现呢?

注意:这是伪代码,请原谅我所做的任何错别字,我试图将其尽可能真实。

  • 提交组件
class Input extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            name: ''
        };
    }

    handleChange = (e) => {
        const { enable } = this.props;
        const id = e.target.id;
        const value = e.target.value;

        this.setState({
            [id]: value
        });

        enable(id, value); // <- Using this here breaks set state.
    }

    render() {
        const { myName } = this.state;

        return (
            <div>
                <input type='text' id='name' onChange={this.handleChange} placeholder='' />
                <input type='text' id='address' onChange={this.handleChange} placeholder='' />
                <!-- there can be more input fields -->
            </div>
        );
    }
}
  • 输入组件
class Parent extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            enableButton: false,
            inputFieldValues: {},
        };
    }

    enable = (value) => {
        const { inputFieldValue } = this.state;
        let changes = inputFieldValues || {};

        changes[key] = value;

        this.setState({
            enableButton: true,
            inputFieldValues: changes
        });
    }

    render() {
        const { enableButton } = this.state;

        return (
            <div>
                <Input enable={this.enable} />
                <Submit enableButton={enableButton} />
            </div>
        );
    }
}
  • 父项
 <title>3D Montageanalysetool</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="shortcut icon" href="#" />
        <link href="index.css" rel="stylesheet" type="text/css"/>

        <script src="Libraries/three.min.js" type="text/javascript"></script>
        <script src="Libraries/OrbitControls.js" type="text/javascript"></script>
        <script src="Libraries/OBJLoader.js" type="text/javascript"></script>
        <script src="Libraries/MTLLoader.js" type="text/javascript"></script>

        <!-- ZURBFundation links-->
        <link href="ZURBFundation/css/foundation.css" rel="stylesheet" type="text/css"/>
        <script src="ZURBFundation/js/vendor/jquery.js" type="text/javascript"></script>





     <script>
                //Detctor shows a warning if the current browser do not support WebGL.
                var renderer = new THREE.WebGLRenderer();
                if (renderer.isWebGLAvailable()===true) {
                    // Initiate function or other initializations here
                    animate();
                } else {
                    var warning = renderer.getWebGLErrorMessage();
                    document.getElementById('container').appendChild(warning);
                }

</script>

2 个答案:

答案 0 :(得分:1)

我不确定您的代码中是否有错误,并且没有在此处共享的伪代码中反映出来,但是基于此,我可以使其正常工作,并且在父级和子级组件中都正确更新了状态(检查console.log)。

https://codesandbox.io/s/r79q9myj8o

答案 1 :(得分:1)

我不太确定我是否了解您的问题,但这是固定的伪代码示例。

我注意到的是

generic_alg.H

我不知道您是否在实际应用中犯了同样的错误,但是我想提一提,这是很粗鲁的错误,可能会导致意外行为,因为您是在更改状态对象,而不是创建新的对象。 React比较对象引用,但不对其进行深入检查。 这个trait_implementation.H应该是const { inputFieldValue } = this.state; let changes = inputFieldValues || {}; changes[key] = value;

此外,您没有为输入提供字段值。虽然,它不会影响状态更改,但随后输入和状态可能会变得不同步。

let changes = inputFieldValues || {};
let changes = { ...inputFieldValues } || {};