Home > Software engineering >  Return value from child component to parent component React
Return value from child component to parent component React

Time:10-12

So I'm trying to use a react Timer in one of my class components. I figured out how to connect it, but now I need to save the time into the parent's state. How can I go upon doing that? Since the time is being measured on the child component. So essentially I need to save the time measured from the child component to the parent's state.

CodePudding user response:

The phrase that comes to mind is Lifting State up. React has a 'top-down' data flow. So your state needs to be initialised in the parent component and passed down to the child components that need it. e.g. (pseudocode, may not work)

function Parent() {
  const [text, setText] = useState('hello world')

  return (
    <>
      <Child text={text} />
      <OtherChild text={text} setText={setText} />
    </>
  )  
}

function Child({ text }) {
  return <p>{text}</p>
}

function OtherChild({ text, setText }) {
  return (
    <input
      onChange={e => setText(e.target.value)}
      value={text} />
  )
}

CodePudding user response:

You'll need to pass a function that updates the parent's state to the child component via props:

In this particular example, both the child and the parent props have a state hook that keeps track of time - the parent's updateParentTime function get's called any time the child's time value changes.

NOTE: it's probably not necessary to keep state in both places...I was just showing an example. If the parent needs has state for time, you could also just pass that down to the child component

const Parent = (props) => {
   const [time, setTime] = useState(0);

   const updateParentTime = (t) => {
      setTime(t);
   }
 
  return (
    <Child updateParentTime={updateParentTime}/>
  )
}

const Child = (props) => {
   const {updateParentTime} = props;
   const [time, setTime] = useState(0);

   useEffect(() => {
      updateParentTime(time)
   }, [time]);

   return (
     <div>
       {/* something goes here */}
     </div>
   )
}

CodePudding user response:

The following defines two React components: Parent and Child.

Parent declares a piece of state named time and a mutator method for that state named setTime.

The current value of time is passed to Child via the prop named time.

setTime is passed to Child via the prop named notify.

Child configures a timer that invokes notify (ie setTime) once a second.

Invoking notify tells React that a state change has occurred and triggers a re-rendering of both components, causing the time to be rendered by each component, once every second.

pre { border: 1px solid black; padding: 10px; }
<script src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>

<script type="text/babel">
const { useState, useEffect } = React

const Parent = () => {
  const [ time, setTime ] = React.useState('--- --- -- ----')
  return <pre>
           Parent: { time }
           <Child notify={setTime} time={ time }/>
         </pre>
}

const Child = ({ notify, time }) => {    
    useEffect(()=>{
      const id = setInterval(() => notify(Date()), 1000)
      return () => clearInterval(id)      
    })

    return <pre>Child: {time}</pre>
}

ReactDOM.render(<Parent/>, document.querySelector('main'))
</script>
<main></main>

  • Related