其他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函数来更新“父”道具:
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
?
我知道上面创建了子代对父代的依赖关系,考虑到我最终需要将dictionary
传递给第二个子代,是否有更好的编程方式来实现这一点?
答案 0 :(得分:0)
您甚至都不会触发传递给组件的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);
}
答案 1 :(得分:0)
//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()方法,如果您未调用该方法,将会触发该方法,希望它会如何触发。
答案 2 :(得分:0)
您不能通过这种方式分配孩子的onChange()
事件处理程序。
相反,您将子事件处理程序称为道具,并将父回调绑定到这些道具。
这个概念被称为lifting state up。
完整的用例演示,您可以在下面找到:
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>
答案 3 :(得分:0)
错误:-没有在onChange
中调用<Input/>
函数,而在<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>