简体   繁体   中英

Can I setState in Parent from Child component?

I would like to clean my code a bit so instead of having one long component I would like to create child component.

In my Parent I have some states I would like to update onClick in Child .

Parent:

const [plan, setPlan] = useState('myPlan');
const [months, setMonths] = useState('2');
const [price, setPrice] = useState(200);

<PlanSelection props={props}
               item={selectedData}
               itemPlan={plan}
 />

Child

const PlanSelection = ({ props, item, itemPlan }) => {

    function handleSubsribe() {
        props.setPlan('Subsribe Only');
        props.setPrice(item.price);
        props.setMonths('24+');
    }

    function handlePay() {
        props.setPlan('Pay to Own');
        props.setPrice(item.pay);
        props.setMonths('12-24');
    }

And just trying to call the functions (in Child component)

<button onClick={handleSubscribe} />
<button onClick={handlePay} />

Using the code above throws error after clicking in one of the buttons:

TypeError: props.setPlan is not a function

But if I don't pass props, setPlan, setPrice, .... will be undefined. Is there a way how to handle it?

Problem

<PlanSelection props={props}
               item={selectedData}
               itemPlan={plan}
 />

You did not pass setPlan to child, you have only passed props , which props has nothing to do with state , selectedData which I'm not sure what's that, and plan , which is the state . In summary you did not pass anything about setState to child component


Solution

Parent

const [plan, setPlan] = useState('myPlan');

<PlanSelection 
  setPlan={setPlan}
 />

Child

const PlanSelection = ({ setPlan }) => {

    function handleSubsribe() {
        setPlan('Subsribe Only');
    }

    function handlePay() {
        setPlan('Pay to Own');
    }

In the code above I've only used setPlan as an example to show you how to setState from child component, you can apply same logic to the rest.

UPDATES Just realized I've made a mistake which you should be worth noting. In your child component you have ({ setPlan }) , this is known as destructuring, which is you are extracting setPlan out of props , hence in your child component, you should not be accessing props.setPlan but setPlan instead. Do take a look at the answer above again

You can simply pass your setState functions as props to your child component. One simple way to do that is:

const [plan, setPlan] = useState('myPlan');
const [months, setMonths] = useState('2');
const [price, setPrice] = useState(200);

<PlanSelection setPlan={setPlan}
               item={selectedData}
               itemPlan={plan}
 />

Here you will be able to update plan state from the child component.

If you want to pass all your setStates to the child, try this.

const handlers = {setPlan, setMonths, setPrice}
    <PlanSelection handlers={handlers}
                   item={selectedData}
                   itemPlan={plan}
     />

const PlanSelection = ({ handlers, item, itemPlan }) => {

You can use setPlan as handlers.setPlan instead of props.setPlan .

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