What's the right way to pass form element state to sibling/parent elements?

后端 未结 10 765
情话喂你
情话喂你 2020-11-29 15:04
  • Suppose I have a React class P, which renders two child classes, C1 and C2.
  • C1 contains an input field. I\'ll refer to this input field as Foo.
  • M
10条回答
  •  佛祖请我去吃肉
    2020-11-29 15:36

    More recent answer with an example, which uses React.useState

    Keeping the state in the parent component is the recommended way. The parent needs to have an access to it as it manages it across two children components. Moving it to the global state, like the one managed by Redux, is not recommended for same same reason why global variable is worse than local in general in software engineering.

    When the state is in the parent component, the child can mutate it if the parent gives the child value and onChange handler in props (sometimes it is called value link or state link pattern). Here is how you would do it with hooks:

    
    function Parent() {
        var [state, setState] = React.useState('initial input value');
        return <>
             setState(v)} />
            
        
    }
    
    function Child1(props) {
        return  props.onChange(e.target.value)}
        />
    }
    
    function Child2(props) {
        return 

    Content of the state {props.value}

    }

    The whole parent component will re-render on input change in the child, which might be not an issue if the parent component is small / fast to re-render. The re-render performance of the parent component still can be an issue in the general case (for example large forms). This is solved problem in your case (see below).

    State link pattern and no parent re-render are easier to implement using the 3rd party library, like Hookstate - supercharged React.useState to cover variety of use cases, including your's one. (Disclaimer: I am an author of the project).

    Here is how it would look like with Hookstate. Child1 will change the input, Child2 will react to it. Parent will hold the state but will not re-render on state change, only Child1 and Child2 will.

    import { useStateLink } from '@hookstate/core';
    
    function Parent() {
        var state = useStateLink('initial input value');
        return <>
            
            
        
    }
    
    function Child1(props) {
        // to avoid parent re-render use local state,
        // could use `props.state` instead of `state` below instead
        var state = useStateLink(props.state)
        return  state.set(e.target.value)}
        />
    }
    
    function Child2(props) {
        // to avoid parent re-render use local state,
        // could use `props.state` instead of `state` below instead
        var state = useStateLink(props.state)
        return 

    Content of the state {state.get()}

    }

    PS: there are many more examples here covering similar and more complicated scenarios, including deeply nested data, state validation, global state with setState hook, etc. There is also complete sample application online, which uses the Hookstate and the technique explained above.

提交回复
热议问题