繁体   English   中英

将子组件单击处理程序绑定到父状态

[英]Bind child component click handler to parent state

其他 SO 答案都没有帮助,所以我认为我在概念上遗漏了一些东西。

我有一个父(包装器)组件和一个子(输入)组件。 父级向下传递一个函数给子级:

const Wrapper = () => {
  const [dictionary, setDictionary] = useState([{ word: "init", definition: "def init" }]);

  const handleWordChange = (e, value) => {
    e.preventDefault();

    /// IS NEVER TRIGGERED
  };

  return (
    <Input setDictionary={{ setDictionary }} onChange={handleWordChange} />
  )
}

子组件处理自己的状态,但应该通过调用 setDictionary 函数来更新 Parent props:

const Input = props => {
  const [definition, setDefinition] = useState("");
  const [word, setWord] = useState("");

  const handleSubmit = e => {
    const { setDictionary } = props.setDictionary;
    e.preventDefault();
    setDictionary([{ word, definition }]);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        name='word'
        onChange={e => setWord(e.target.value)}
        onFocus={() => setWord("")}
        placeholder='Word'
        type='text'
        value={word}
      />

      <input
        name='definition'
        onChange={e => setDefinition(e.target.value)}
        onFocus={() => setDefinition("")}
        placeholder='Definition'
        type='text'
        value={definition}
      />
      <input type='submit' value='Submit' />
    </form>    
  )
}

我看到的其他答案建议将回调传递给 Child (setDictionary),但是 onChange 处理程序永远不会在更改时调用。 我也尝试使用 onSubmit 代替。

如何成功更新dictionary 我知道上面创建了 Child 对 Parent 的依赖,考虑到我最终需要将dictionary传递给第二个孩子,是否有更好的编程方式来实现这一点?

你甚至没有触发传递给组件的 onChange

  <Input setDictionary={{ setDictionary }} onChange={handleWordChange} />

你必须完全按照你命名道具的方式做,比如 props.onChange

//there is no props.onChange here in this component

const Input = props => {
  const [definition, setDefinition] = useState("");
  const [word, setWord] = useState("");

  const handleSubmit = e => {
    const { setDictionary } = props.setDictionary;
    e.preventDefault();
    setDictionary([{ word, definition }]);
    //like here
    props.onChange(any arguments);

  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        name='word'
        onChange={e => setWord(e.target.value)}
        onFocus={() => setWord("")}
        placeholder='Word'
        type='text'
        value={word}
      />

      <input
        name='definition'
        onChange={e => setDefinition(e.target.value)}
        onFocus={() => setDefinition("")}
        placeholder='Definition'
        type='text'
        value={definition}
      />
      <input type='submit' value='Submit' />
    </form>    
  )
}

如果我重命名

 <Input setDictionary={{ setDictionary }} onInputChanged={handleWordChange} />

我会这样称呼它

const handleSubmit = e => {
    const { setDictionary } = props.setDictionary;
    e.preventDefault();
    setDictionary([{ word, definition }]);
    //like here
    props.onInputChanged(any arguments);

  }
//there is not props.onChange here in this component

const Input = props => {
  const [definition, setDefinition] = useState("");
  const [word, setWord] = useState("");

  const handleSubmit = e => {
    const { setDictionary } = props.setDictionary;
    e.preventDefault();
    setDictionary([{ word, definition }]);
    //like here
    props.onChange(any arguments);

  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        name='word'
        onChange={e => {
          setWord(e.target.value)
         props.onChange();
        }}
        onFocus={() => setWord("")}
        placeholder='Word'
        type='text'
        value={word}
      />

      <input
        name='definition'
        onChange={e => {
    setDefinition(e.target.value)
              props.onChange();
    }}
        onFocus={() => setDefinition("")}
        placeholder='Definition'
        type='text'
        value={definition}
      />
      <input type='submit' value='Submit' />
    </form>    
  )
}

在您的输入组件中使用父 onChange() 方法,如果您没有调用该方法,它将被触发而不是如何触发我希望这对您有所帮助。

您不能以这种方式分配孩子的onChange()事件处理程序。

相反,您将子事件处理程序称为道具并将父回调绑定到这些道具。

这个概念被称为提升状态

您可以在下面找到您的用例的完整现场演示:

 const { render } = ReactDOM, { useState } = React const Input = ({onInput}) => { const [word, setWord] = useState(''), [definition, setDefinition] = useState('') return ( <form onSubmit={e => (e.preventDefault(), onInput(word, definition))}> <label> Word: <input onChange={({target:{value}}) => setWord(value)} /> </label> <label> Definition: <input onChange={({target:{value}}) => setDefinition(value)} /> </label> <input type="submit" value="Submit" /> </form> ) } const List = ({list}) => ( <ul> { list.map(({word,definition},key) => <li {...{key}}><strong>{word}</strong> - {definition}</li>) } </ul> ) const Parent = () => { const [dictionary, setDictionary] = useState([]), onDicionaryItemSubmit = (word,definition) => setDictionary([...dictionary, {word,definition}]) return ( <div> <Input onInput={onDicionaryItemSubmit} /> <List list={dictionary} /> </div> ) } render ( <Parent />, document.getElementById('root') )
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

错误:- 未在<Input/>调用onChange函数并在<Wrapper />设置字典状态。
这是您查询的有效解决方案。

 const {useState} = React; const Wrapper = () => { const [dictionary, setDictionary] = useState([ { word: "computer", definition: "an electronic device for storing and processing data" } ]); const handleWordChange = (e, value) => { e.preventDefault(); let updateDictionary = [...dictionary]; updateDictionary.push(value); setDictionary(updateDictionary); // console.log(updateDictionary); /// IS NEVER TRIGGERED }; return ( <React.Fragment> <Input onChange={handleWordChange} /> {dictionary.length > 0 ? ( <table> <tr> <th>WORD</th> <th>DEFINITION</th> </tr> {dictionary.map(datum => ( <tr> <td>{datum.word}</td> <td>{datum.definition}</td> </tr> ))} </table> ) : null} </React.Fragment> ); }; const Input = props => { const [definition, setDefinition] = useState(""); const [word, setWord] = useState(""); const handleSubmit = e => { e.preventDefault(); props.onChange(e, { word, definition }); }; return ( <form onSubmit={handleSubmit}> <input name="word" onChange={e => setWord(e.target.value)} onFocus={() => setWord("")} placeholder="Word" type="text" value={word} /> <input name="definition" onChange={e => setDefinition(e.target.value)} onFocus={() => setDefinition("")} placeholder="Definition" type="text" value={definition} /> <input type="submit" value="Submit" /> </form> ); }; ReactDOM.render(<Wrapper />, document.getElementById('root'));
 table, th, td { border: 1px solid black; } table { margin-top: 20px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM