首页 > 解决方案 > 将带有 1 个 arg 的函数作为道具传递给子组件

问题描述

我正在尝试将setResponse()函数作为 aprop传递给子组件。该函数从子组件中获取一个参数(响应)并调用handleChange()具有 3 个参数(父组件中可用的响应和 2 个参数)的函数。

我遇到的问题是我的setResponse函数已传入但仅在第一次渲染时定义,即当我console.log()在子组件函数中正确显示在第一次渲染但随后未定义时。我在下面提出了问题的代码,但在下面添加了更多上下文以防需要更多上下文。

更新:我想我可能需要在 FragmentWrapper 的 useEffect 中添加 setResponse 作为依赖项,但这会导致无限循环......

更新 2:制作了一个代码沙箱,用于玩 https://codesandbox.io/s/gracious-sunset-00hzl?file=/src/App.js

更新 3:我认为问题很可能出在父组件中。第一次渲染 FragmentWrapper 时,它具有正确的道具,因此父组件中必须发生某些事情(状态更改或其他?),这将导致 FragmentWrapper 的道具更改并触发重新渲染。也不确定为什么发生的任何事情都会导致 setResponse 变得未定义......

const DisplayQuestion = ({ answers, question, onChange }) => {
  return React.createElement(question.component, {
    setResponse: answer => {
      handleChange(answer, question.id, answers)  
    }, // answer passed in from child, question.id and answers available in parent
  })
}

下面是我尝试过的其他东西,但这显示了相同的行为(仅在第一次渲染时设置然后未定义)。

const DisplayQuestion = ({ answers, question, onChange }) => {
  const setFunc = (answer) => { 
    handleChange(answer, question.id, answers)
  }
  return React.createElement(question.component, {
    setResponse: setFunc,
    }, 
}

上下文代码

const DisplayQuestion = ({ answers, question, onChange }) => {
  const handleChange = (answer, id, answers) => {
    onChange({ ...answers, [id]: answer })
  }

  return React.createElement(question.component, {
    response: answers[question.id] ? answers[question.id] : null,
    setResponse: answer => {
      handleChange(answer, question.id, answers)
    },
    component: RadioQuestion,
    ...question, // these are other (passed in) props 
  })
}
export const RadioQuestion = props => (
  <FragmentWrapper component={RadioFragment} {...props} />
)
const FragmentWrapper = ({
  questionText,
  response,
  setResponse,
  component: Fragment  
}) => {
  const [value, setValue] = useState(response || '')

  useEffect(() => {
    console.log(setResponse) // prints correct 1st render then undefined
    setResponse && setResponse(value)
  }, [value])

  const handleChange = setter => event => {
    event && event.target ? setter(event.target.value) : setter(event)
  }
  
  const fragmentProps = { value, setValue, options, handleChange }  
  return (
    <>
      <Typography>{questionText}</Typography>
      <Fragment {...fragmentProps} /> 
      // Fragment=RadioQuestion as specified in DisplayQuestion
    </>
  )
}
export const RadioFragment = ({
  value,
  setValue,
  options,
  handleChange,
}) => {
  return (
    <FormControl>
      <RadioGroup value={value} onChange={handleChange(setValue)} >
        {options.map(option => (
          <FormControlLabel value={option} control={<Radio />} />
        ))}
      </RadioGroup>
    </FormControl>
  )
}

标签: javascriptreactjsreact-props

解决方案


推荐阅读