[英]Event-handler setting state from a child component doesn't re-render parent component
[英]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.