zoukankan      html  css  js  c++  java
  • react 获取子组件的 state (转发)

    原文:How to access childs state from parent component in React

    Are you seeking how to access a child state from a parent component?

    This is the article you’ve been waiting for!

    The answer: Use a callback function

    The most common method is to make a callback function that the child component will trigger and toss the state values upward.

    Let’s take a look at a couple methods.

    Get state value onClick event

    One method is to update state, and when a click happens, use a callback function that gives the parent component the values.

    Here’s an article that covers this method more in detail, “How to get form data on submit in ReactJS“.

    Get state value on onChange event

    The method above covers how to pass the child state over a click event.

    But what about when input field changes?

    We sure can do that as well! Let’s take a look at how.

    class ChildComponent extends React.Component {
    
      state = {
        username: '',
        password: '',
      }
    
      handleChange = e => {
        this.setState({ [e.target.name]: e.target.value }, () => {
          if (this.props.onChange) {
            this.props.onChange(this.state);
          }
        })
      };
    
      render() {
        return (
          <>
            <div>
              <div>Username:</div>
              <input name="username" onChange={this.handleChange} />
            </div>
            <br />
            <div>
              <div>Password:</div>
              <input name="password" onChange={this.handleChange} />
            </div>
            <br />
            <div>
              <button onClick={this.handleSubmit}>Submit</button>
            </div>
          </>
        );
      }
    }
    

      

    Let’s take a look at the the code snippet that handles React state update and returns the new state object to the parent component.

    state = {
      username: '',
      password: '',
    }
    
    handleChange = e => {
      this.setState({ [e.target.name]: e.target.value }, () => {
        if (this.props.onChange) {
          this.props.onChange(this.state);
        }
      })
    };
    

      

    In the handleChange() method, I’m calling this.setState(), and updating the component state object with the new values.

    In this.setState(), i’m also passing a function as a second parameter. That function gets called once the React state object has been modified.

    In that callback function, I’m checking if the React parent component provided a prop called onChange(), and if so, pass the updated child component state object.

    Let’s see how the code looks like in the parent component:

    function App() {
    
      const eventhandler = data => console.log(data)
    
      return <ChildComponent onChange={eventhandler} />;
    }
    

    Fairly simple. As I’m typing I see a log as such:

    Object {username: "a", password: ""}
    Object {username: "a", password: "s"}
    Object {username: "a", password: "ss"}
    Object {username: "a", password: "sss"}
    

      

    Is there a more recommended way after React state has changed?

    Yes! Let’s take a look at React's componentDidUpdate lifecycle.

    Get state value on React componentDidUpdate

    If you’re curious to read up on how React componentDidUpdate works, check out this article, “How does React componentDidUpdate work“.

    class ChildComponent extends React.Component {
    
      state = {
        username: '',
        password: '',
      }
    
      handleChange = e => this.setState({ [e.target.name]: e.target.value });
    
      componentDidUpdate() {
        if (this.props.onChange) {
          this.props.onChange(this.state);
        }
      }
    
      render() {
        return (
          <>
            <div>
              <div>Username:</div>
              <input name="username" onChange={this.handleChange} />
            </div>
            <br />
            <div>
              <div>Password:</div>
              <input name="password" onChange={this.handleChange} />
            </div>
            <br />
            <div>
              <button onClick={this.handleSubmit}>Submit</button>
            </div>
          </>
        );
      }
    }
    

     

    The only change here is to move the callback function in this.setState() onto the componentDidUpdate lifecycle.

    This may be a more beneficial approach because:

    • You have access to previous props and state for comparison
    • It’s better suited when React performs batching
    • More consistent code logic

     

    In the example above I demonstrated a class component, what if you’re using a functional component?

    You can use the React useEffect hook to emulate componentDidUpdate.

    Get state value on React useEffect hook

    Here’s how we can pass the state to the parent component with the React useEffect hook:

    function ChildComponent(props) {
    
      const [formData, setFormData] = React.useState({ username: '', password: '' });
    
      const handleChange = e => setFormData({ ...formData, [e.target.name]: e.target.value });
    
      React.useEffect(() => {
        if (props.onChange) {
          props.onChange(formData)
        }
      }, [formData.username, formData.password])
    
      return (
        <>
          <div>
            <div>Username:</div>
            <input name="username" onChange={handleChange} />
          </div>
          <br />
          <div>
            <div>Password:</div>
            <input name="password" onChange={handleChange} />
          </div>
          <br />
        </>
      );
    }
    

      

    Get state with React useRef or createRef

    This certainly NOT recommended, but it’s a nice to know.

    Before you get the reference from a component, make sure your child component is a class type.

    If you try to get the reference from a function component, your code will break.

    Type '{ ref: MutableRefObject<any>; }' is not assignable to type 'IntrinsicAttributes & { children?: ReactNode; }'.
      Property 'ref' does not exist on type 'IntrinsicAttributes & { children?: ReactNode; }'

    All this really means, is that functional components don’t have an instance. They’re stateless.

    But if your child component is a class type, then this is how you get the state from it with React useRef hook or createRef().

    But if your child component is a class type, then this is how you get the state from it with React useRef hook or createRef().

    function App() {
    
      const childCompRef = React.useRef(null);
    
      React.useLayoutEffect(() => {
        console.log(childCompRef)
      }, [])
    
      return <ChildComponent ref={childCompRef} />;
    }
    

      

    And the output on the console should look like this:

    current: ChildComponent
      props: Object
      context: Object
      refs: Object
      updater: Object
      state: Object
        username: ""
        password: ""
      handleChange: function () {}
      _reactInternalFiber: FiberNode
      _reactInternalInstance: Object
      <constructor>: "ChildComponent"
    

    You can then go through the object reference path to get to the state object

    childCompRef.current.state // {username: "", password: ""}
    

      

    The only caveat here is that this only works for the initial state. If your child component state is updated, the reference variable will not be updated with the new values.

  • 相关阅读:
    在线学习VIM
    对三叉搜索树的理解
    Suffix Tree
    Skip list
    中文分词算法
    土豆的seo
    Gentle.NET文档(链接)
    a标签的link、visited、hover、active的顺序
    html dl dt dd标签元素语法结构与使用
    WEBZIP为什么打不开网页
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/14417645.html
Copyright © 2011-2022 走看看