1

I am trying to build a website to convert recipes to a different number of servings. I am using React. I have setup a component to take the number of original servings, new number of servings, and number of ingredients. It will not update in the App.js file when I change the value in the PreInputs component.

App.js:

const App = () => {
  //define variables using states
  const [numIngredients, setNumIngredients] = useState(5);
  const [originalServings, setOriginalServings] = useState(8);
  const [newServings, setNewServings] = useState(4);
  
  //create handling functions for the variables
  const handleNumIngredients = (num) => {
    setNumIngredients(num);
  }

  const handleOriginalServings = (num) => {
    setOriginalServings(num)
  }

  const handleNewServings = (num) => {
    setNewServings(num);
  }

  
  return (
  <div>
    <Header title="test"/>
    <PreInputs changeNumIngredients={handleNumIngredients} changeOriginalServings={handleOriginalServings} changeNewServings={handleNewServings}/>
    <h1>{originalServings}</h1>
  </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'))

PreInputs.js:

import React, { useCallback, useState } from 'react';

export const PreInputs = (props) => {
    const numOriginalServings = useState(0)

    const handleOriginalServingsChange = (e) => {
        const originalServings = e.target.value;
        props.changeOriginalServings(originalServings)
    }
    
    return (
        <div className='pre-inputs'>
            <form>
                <label>Original Servings: </label>
                <input value={numOriginalServings} onChange={handleOriginalServingsChange} type='number' />
                <button></button>
            </form>
            <h1>Placeholder</h1>
        </div>
    );
}
  • The `useState` hook use isn't correct in the `PreInputs` child component, you should array destructure assign the state and updater function. You also only consume the `changeOriginalServings` prop, did you need to use the other two that were passed? – Drew Reese Jul 14 '21 at 06:05
  • @DrewReese Thank you, I am new to React. Could you point more towards the correct Syntax for that? – RaidingGames Jul 14 '21 at 06:11
  • It will look suspiciously similar to the `useState` usage in the parent `App` component, but check the [docs](https://reactjs.org/docs/hooks-reference.html#usestate). [Lifting State Up](https://reactjs.org/docs/lifting-state-up.html) also explains the pattern you are trying to use, passing a callback to a child component to update state in a parent. Can you also clarify more what isn't updating in the parent component? – Drew Reese Jul 14 '21 at 06:13
  • Does this answer your question? [How to pass data from child component to its parent in ReactJS?](https://stackoverflow.com/questions/38394015/how-to-pass-data-from-child-component-to-its-parent-in-reactjs) – poPaTheGuru Jul 14 '21 at 06:21

3 Answers3

1

It is anti-pattern in React to store passed props into local state, so you don't really need the numOriginalServings state in PreInputs. Pass originalServings to PreInputs to be used as the default value of the input and pass the updated input value back to the parent component.

PreInputs

const PreInputs = (props) => {
  const handleOriginalServingsChange = (e) => {
    const originalServings = e.target.value;
    props.changeOriginalServings(originalServings);
  };

  return (
    <div className="pre-inputs">
      <form>
        <label>Original Servings: </label>
        <input
          defaultValue={props.originalServings} // <-- initialize input
          onChange={handleOriginalServingsChange}
          type="number"
        />
      </form>
      <h1>Placeholder</h1>
    </div>
  );
};

Parent

function App() {
  //define variables using states
  const [numIngredients, setNumIngredients] = useState(5);
  const [originalServings, setOriginalServings] = useState(8);
  const [newServings, setNewServings] = useState(4);

  //create handling functions for the variables
  const handleNumIngredients = (num) => {
    setNumIngredients(num);
  };

  const handleOriginalServings = (num) => {
    setOriginalServings(num);
  };

  const handleNewServings = (num) => {
    setNewServings(num);
  };

  return (
    <div>
      <Header title="test"/>
      <h1>{originalServings}</h1>
      <PreInputs
        originalServings={originalServings} // <-- pass state
        changeOriginalServings={handleOriginalServings} // <-- pass callback
      />
    </div>
  );
}

Edit how-can-i-send-data-from-a-child-to-a-parent-functional-component-in-reactjs

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

if you want to send data to the parent component

you have 3 ways for it

1- use redux

2- use context

3- make function in the parent component and get data in this function and sent function to the child component
0

According to good programming practice, you shouldn't transfer state this way. For small Apps you should use context.

It's really simple and superfast, especially for data reads.

Amped
  • 21
  • 2