0

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 ?

  • You can, but `handleSubsribe()` and `handlePay()` should be declared in the parent component and passed to the child as props. – secan Aug 24 '21 at 13:21
  • Does this answer your question? [How can I update the parent's state in React?](https://stackoverflow.com/questions/35537229/how-can-i-update-the-parents-state-in-react) – PRSHL Aug 24 '21 at 13:24
  • This is an example of what I meant in my previous comment: https://jsfiddle.net/bcs6ejpk/1/ – secan Aug 24 '21 at 13:37

3 Answers3

0

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

Isaac
  • 12,042
  • 16
  • 52
  • 116
0

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.

Theo Martinez
  • 129
  • 1
  • 9
0

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.

Chuck
  • 776
  • 5
  • 18
  • 1
    I dont think `props={...props}` is a good idea, first of all, we should never name `props`, `props`. Second, kinda personal preference, i dont really wanna pass all parent's `props` over to child, after all we human never inherit all the traits from our parent, do we :p – Isaac Aug 24 '21 at 13:29
  • Agreed. Passing `props` directly to the child is not my favorite too. – Chuck Aug 24 '21 at 13:31