简体   繁体   中英

React: Changed state in Child component. How to see the change in parent component?

For a website I am working on I have made a component with checkboxes that triggers a state change in a parent component. I have checked in the console through the child component that the state is changed, but I want the parent component to "notice" the change too. I have tried useEffect and componentDidUpdate but they both do not get triggered by the state change.

To clarify, the structure looks like this:

Parent: Has the initial state Child: Gets access to state through parent, and changes state

On a page refresh the parent notices the state change, but I want this without having to refresh the page.

I hope this makes sense, thank you in advance:)

Is this what you are looking for?

import React, { useState } from "react";

const Parent = () => {
  const [someState, setSomeState] = useState("Initial Some State");

  const onChangeSomeState = (newSomeState) => {
    setSomeState(newSomeState);
  };

  return (
    <div>
      Parent:
      <Child
        someState={someState}
        onChangeSomeState={onChangeSomeState}
      ></Child>
    </div>
  );
};

const Child = ({ someState, onChangeSomeState }) => {
  const handleChangeStateClick = () => {
    onChangeSomeState("New Some State from Child");
  };
  return (
    <div>
      Child:{someState}
      <input
        type="button"
        onClick={handleChangeStateClick}
        value="Change state from Child"
      ></input>
    </div>
  );
};

export default Parent;

If I understood your issue correctly, you can pass a callback function into child component. In that way, you'll receive value from callback in your parent component like this:

const ParentComponent = () => {
    const [someState, setSomeState] = useState()

    const childCallback = (value) => {
       setSomeState(value)
    }

    return <ChildComponent callback={childCallback} />
}

The nature of react means that data flows down the dom tree. This is made possible using props.

When props change it is noticed by react and that causes the recipient of the props to re-render. However, as you have discovered this is a uni-directional relationship, only ever going parent to child.

The beauty of javascript is that you can treat functions just like strings or numbers and pass them around. In this case as props.

So while the child can't 'tell' the parent something has changed directly, the parent can pass in a function that the child can use to make the change known.

This pattern of passing down a value from a parent and a 'handler' function the child can use to notify the parent is extremely common and a good one you get your head around.

Take a standard text input as an example.

const Parent = () => {
  // This is our parent's state
  const [inputValue, setInputValue] = useState('hello world');

  // This is the handler we will give to the child to let us know of changes
  const handleInputChange = (e) => setInputValue(e.target.value) 

  return <input
    value={inputValue}
    onChange={handleInputChange} 
  />
}

In the above example the child (the input) when it changes will call the function supplied to it and that will update the parent's state. Any state updates on a react component (just like a prop change) will cause a re-render and therefore a visual update.

I used a built in <input> in any child you write yourself just needs to accept a 'handler function' which you call inside your child when you want to let the parent know that something has happened.

As my understanding, if I don't get wrong, I think you should pass the trigger event from parent to child as props.

parent ( functional component + hook ):

const [ userName, setUserName ] = useState("");

return(
  <Child doChangeProps={setUserName} />
)

child ( functional component + hook ):

const { doChangeProps } = props;

return(
  <input onChange={ e => { doChangeProps(e); } } />
)

or, you can use context for more simple data flow.

function ParentComponent(){
    const [state, setState] = useState()

    useEffect(() => {
       console.log({ state });
    },[state])

    return <ChildComponent state={state} setState={setState} />
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM