2
votes

I'm using React hooks to set state. There is a parent component that has multiple child components. The parent component has the state, and passes functions to the children components to update its state as callbacks.

The child components are the same, they just receive different function callbacks to update the related state in the parent.

My question is, can I write one handleChange function in the parent that will allow me to use this function callback structure to set multiple state values in the parent?

Parent component:

import React, { useState } from 'react'
import Control from './Control'

const Sort = () => {

  const [controlUpValues, setControlUpValues] = useState([])
  const [controlDownValues, setControlDownValues] = useState([])

  const handleControlUpChange = values => {
    setControlUpValues(values)
  }

  const handleControlDownChange = values => {
    setControlDownValues(values)
  }

  return
    <>
      <Control
        setControlItems={handleControlUpChange}
      />

      <Control
        setControlItems={handleControlDownChange}
      />
    </>
  )
}

export default Sort

Child component:

import React, { useState } from 'react'
import { Button, TextField } from '@material-ui/core'

function Control({ setControlItems }) {
  const [controlInputValues, setControlInputValues] = useState([])
  const [inputRef, setInputRef] = useState([])
  const [inputValues, setInputValues] = useState([])

  const handleValueChange = () => setInputValues(inputRef.value)

  const addValuesToItems = () => {
    setControlItems(inputValues)
  }

  return (
    <div>
      <TextField
        inputRef={ref => setInputRef(ref)}
        value={controlInputValues ? controlInputValues : ''}
        onChange={handleValueChange}
      />
      <Button
        onClick={addValuesToItems}
      >
        Add
      </Button>
    </div>
  )
}

export default Control
1

1 Answers

1
votes

You can have an object containing the functions to update the state :

Parent

import React, { useState } from 'react'
import Control from './Control'

const Sort = ({ classes }) => {

  const [controlBoostValues, setControlBoostValues] = useState([])
  const [controlBuryValues, setControlBuryValues] = useState([])

  const functions = {
    boost: setControlBoostValues,
    bury: setControlBuryValues
  }

  const handleChange = (key, values) => functions[key](values);

  return
    <>
      <Control
        setControlItems={handleChange}
      />

      <Control
        setControlItems={handleChange}
      />
    </>
  )
}  

Child :

import React, { useState } from 'react'
import { Button, TextField } from '@material-ui/core'

function Control({ setControlItems }) {
  const [controlInputValues, setControlInputValues] = useState([])
  const [inputRef, setInputRef] = useState([])
  const [inputValues, setInputValues] = useState([])

  const handleValueChange = () => setInputValues(inputRef.value)

  const addValuesToItems = () => {
    setControlItems("boost" , inputValues)
  }


  return (
    <div>
      <TextField
        inputRef={ref => setInputRef(ref)}
        value={controlInputValues ? controlInputValues : ''}
        onChange={handleValueChange}
      />
      <Button
        onClick={addValuesToItems}
      >
        Add
      </Button>
    </div>
  )
}

export default Control