【问题标题】:Can I consolidate multiple functions that set state based on callbacks from React child components?我可以合并多个基于 React 子组件回调设置状态的函数吗?
【发布时间】:2020-03-06 19:03:28
【问题描述】:

我正在使用 React 钩子来设置状态。有一个父组件有多个子组件。父组件拥有状态,并将函数传递给子组件以回调的方式更新其状态。

子组件都是一样的,只是接收到不同的函数回调来更新父组件中的相关状态。

我的问题是,我可以在父级中编写一个handleChange 函数,以允许我使用此函数回调结构在父级中设置多个状态值吗?

父组件:

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

子组件:

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

【问题讨论】:

    标签: javascript reactjs ecmascript-6 react-hooks


    【解决方案1】:

    您可以拥有一个包含更新状态的函数的对象:

    家长

    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}
          />
        </>
      )
    }  
    

    孩子:

    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
    

    【讨论】:

    • 通常这是有道理的,但是在孩子中硬编码密钥?
    • 只有一种类型的子组件,其中有一个声明的函数被调用以在点击时更新项目,无论是 boost 还是bury。我在您的建议中没有看到一种方法来区分回调中哪些项目是“提升”与“埋葬”,因为在子组件之间只有一个 addValuesToItems 函数共享。
    • @Taki 有没有办法将此键添加为子声明中的标识符,而不是在子声明中设置它?即子级必须在功能上基本保持不变,而不是在所有子级之间共享,那么如何设置子级声明标识符?
    • @lane taki 向后命名道具,但只需在父级中执行 setControlItems={values =&gt; handleChange('boost', values)} 即可。问题解决了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2020-10-01
    • 2020-07-23
    相关资源
    最近更新 更多