How to Group State and Pass it Down to Children with React Hooks

Man making fire on lake beach in forest.

Sometimes we have a React component that needs to pass many state values to its parent. Sometimes we even have grandchildren or props several generations deep that need to set state to their grandparent. See this example:


import { useState } from 'react'
export default function Card(){
  const [cardNumber, setCardNumber] = useState('')
  const [cardNumber2, setCardNumber2] = useState('')
  const [cardNumber3, setCardNumber3] = useState('')
  const [cardNumber4, setCardNumber4] = useState('')
  const [cardNumber5, setCardNumber5] = useState('')
  const [cardNumber6, setCardNumber6] = useState('')


  const cardState = {
    cardNumber, setCardNumber,
    cardNumber2, setCardNumber2,
    cardNumber3, setCardNumber3,
    cardNumber4, setCardNumber4,
    cardNumber5, setCardNumber5,
    cardNumber6, setCardNumber6
  }

  return(
    <>
      <CardNumber 
        cardNumber={cardNumber} 
        setCardNumber={setCardNumber}
        cardNumber2={cardNumber2} 
        setCardNumber2={setCardNumber2}
        cardNumber3={cardNumber3} 
        setCardNumber3={setCardNumber3}
        cardNumber4={cardNumber4} 
        setCardNumber4={setCardNumber4}
        cardNumber5={cardNumber5} 
        setCardNumber5={setCardNumber5}
        cardNumber6={cardNumber6} 
        setCardNumber6={setCardNumber6}
      />
    </>
  )
}

Instead of passing all of that state as props to the child component, we can actually just save all of the state to an object, pass just the object to the child component, and then destructure the object to get all of the functions and variables out in the destination child! If it is a grandchild, we don’t even have to destructure until the destination!:

import { useState } from 'react'
export default function Card(){
  const [cardNumber, setCardNumber] = useState('')
  const [cardNumber2, setCardNumber2] = useState('')
  const [cardNumber3, setCardNumber3] = useState('')
  const [cardNumber4, setCardNumber4] = useState('')
  const [cardNumber5, setCardNumber5] = useState('')
  const [cardNumber6, setCardNumber6] = useState('')

  //Set all of the state variables and functions to the cardState object
  //We are using the "Object Literal Property Value Shorthand" from JS ES6 below (we don't need to pass the {property:value} pair when assigning the object properties - just the variable name, and the key is automatically set to be the variable's value)
  const cardState = {
    cardNumber, setCardNumber,
    cardNumber2, setCardNumber2,
    cardNumber3, setCardNumber3,
    cardNumber4, setCardNumber4,
    cardNumber5, setCardNumber5,
    cardNumber6, setCardNumber6
  }

  return(
    <>
      <CardNumber 
        cardState={cardState}
      />
    </>
  )
}

// CardNumber Child Component: 
export default function CardNumber({
  cardState,
}){
  //Destructure all of the state variables and functions in the child component!
  const {
    cardNumber, setCardNumber,
    cardNumber2, setCardNumber2,
    cardNumber3, setCardNumber3,
    cardNumber4, setCardNumber4,
    cardNumber5, setCardNumber5,
    cardNumber6, setCardNumber6
  } = cardState
}

Awesome, right?! I used to think that it was a pretty serious limitation of React hooks that we couldn’t pass all of the parent’s state in one package as an object. Then it took me around a year to realize that it’s actually possible to do this. I was working with some components that were inheriting lots of state from their parents, and went to bed thinking “there must be a better way to do this!”, then first thing in the morning I woke up, and thought “Can’t I just put them all in an object?”. I let the thought drift off, and went back to sleep. But later on I tried it, and imagine my excitement when I found out it worked!

Good luck out there!

//Omar ?


Object Property Value Shorthand with JS ES6

ES6 Object Literal Shorthand

Lake camping image “Free Man” by Tom Pottiger on Unsplash

Subscribe to new blog posts