NextJS/React - Is it possible to combine multiple child component states into one parent component state?

Viewed 34

Problem

I have multiple Child components, which are able to pass up its state to a Parent component. I now want to be able to render multiple Parent components within a Grandparent component, and then be able to take the states of each Parent component and combine it into 1 singular state/object within the Grandparent component. Please refer to this codesandbox or look at the code below.

Child.tsx

import TextField from "@mui/material/TextField"

type Props = {
  valueChange: (e: React.ChangeEvent<HTMLInputElement>) => void
  id: string
}

const Child: React.FC<Props> = ({ valueChange, id }) => {
  return (
    <>
      <TextField
        id={id}
        label={id}
        name={id}
        variant="outlined"
        onChange={valueChange}
      />
    </>
  )
}

export default Child

Child2.tsx

import Checkbox from "@mui/material/Checkbox"

type Props = {
  valueChange: (e: React.ChangeEvent<HTMLInputElement>) => void
  id: string
}

const Child2: React.FC<Props> = ({ valueChange, id }) => {
  return (
    <>
      <Checkbox name={id} onChange={valueChange} />
    </>
  )
}

export default Child2

Parent.tsx

import { useState } from "react"
import Child from "./Child"
import Child2 from "./Child2"

type Props = {}

const Parent: React.FC<Props> = ({}) => {
  const [values, setValues] = useState({})

  const valuesChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const name = e.target.name

    let value: any
    if (name === "bool") {
      value = e.target.checked
    } else {
      value = e.target.value
    }

    setValues((prev) => {
      return { ...prev, [name]: value }
    })
  }

  return (
    <>
      <div>{JSON.stringify({ values })}</div>
      <div>
        <Child valueChange={valuesChange} id={"Text1"} />
        <Child valueChange={valuesChange} id={"Text2"} />
        <Child2 valueChange={valuesChange} id={"bool"} />
      </div>
    </>
  )
}

export default Parent

Grandparent.tsx

import { Button } from "@mui/material"
import Parent from "./Parent"

const Grandparent: React.FC = () => {
  const buttonClick = () => {
    alert(
      "Want this to look like following \n" +
        "data: [{Parent1 state},{Parent2 state}]"
    )
  }

  return (
    <>
      <Parent />
      <Parent />
      <Button onClick={buttonClick}>Get Grandparent State</Button>
    </>
  )
}

export default Grandparent
1 Answers

Just move state to the highest parent (grandparent) in your case which needs them. You can then pass what state each child component needs as props accordingly.

Thus the state in your case should be in grandpa component. It is passed to each parent as <Parent state={state.child1} /> and so on for others. The onchange will be complex though.

Related