这里我有三个组件。每当我单击任何子组件(
First
和 Second
)中的按钮时,父(Test
)组件应该显示输入到子组件中的文本。问题是每当我单击其他子组件的按钮时,都会使用来自该特定组件的数据创建一个新数组。
这是代码:
测试组件:
function Test() {
const [ChildData , setChildData] = useState('');
console.log(ChildData)
return (
<div>
<h1>Test</h1>
<div>
{ChildData? <div>{ChildData.map((data)=>{return <div>{data}</div> })}</div>:null }
</div>
<First passChildData={setChildData}/>
<Second passChildData={setChildData}/>
</div>
)
}
第一部分:
function First(props) {
const [Data, setData] = useState('');
const [Items, setItems] = useState('')
const handlechange = (e)=>{
setData(e.target.value)
}
const handleClick = ()=>{
if(Data != ''){
setItems((prevData)=>{
const newData = [...prevData,Data];
props.passChildData(newData)
return newData
})
setData('')
}else{
console.log("enter something")
}
}
return (
<div>
<h1>First</h1>
<input type="text" onChange={handlechange} value={Data}/>
<button onClick={handleClick}>Add</button>
{Data}
<div>{Items? <div>{Items.map((item)=>{return <div>{item}</div> })}</div>:null }</div>
</div>
)
}
第二部分:
function Second(props) {
const [Data, setData] = useState('');
const [Items, setItems] = useState('')
const handlechange = (e)=>{
setData(e.target.value)
}
const handleClick = ()=>{
if(Data != ''){
setItems((prevData)=>{
const newData = [...prevData,Data];
props.passChildData(newData)
return newData
})
setData('')
}else{
console.log("enter something")
}
}
return (
<div>
<h1>Second</h1>
<input type="text" onChange={handlechange} value={Data}/>
<button onClick={handleClick}>Add</button>
{Data}
<div>{Items? <div>{Items.map((item)=>{return <div>{item}</div> })}</div>:null }</div>
</div>
)
}
我期待的是:
First
组件中输入“What”时;Second
组件;First
组件Second
组件我想要“你叫什么名字?” (不管它是在不同的 div 还是在行中;我希望每个项目都按照输入的顺序显示)显示在父 (
Test
) 组件中。
首先,我不会有两个组件 -
First
和 Second
- 除了它们的标题外几乎相同;我会有一个带有 heading
作为道具的组件。
其次,我会使用带有
<form>
处理程序的 onSubmit
而不是带有 <button>
处理程序的 onClick
因为这将允许用户添加项目,例如,在输入时按 [Enter]领域有重点。
第三,我会使用
useEffect
钩子来监听 First
组件对 Items
数组的变化,然后在有变化时调用 passChildData
prop 函数。请注意,引用数组的变量应使用空数组进行初始化,例如:const [Items, setItems] = useState([])
.
最终代码如下:
function Test() {
const [ChildData, setChildData] = useState([]);
const setItem = (newItem) => {
setChildData([...ChildData, newItem]);
}
return (
<div>
<h1>Test</h1>
<div>
{ChildData.map((data, index) => <div key={index}>{data}</div>)}
</div>
<First heading="First" passChildData={setItem}/>
<First heading="Second" passChildData={setItem}/>
</div>
)
}
function First(props) {
const [Data, setData] = useState('');
const [Items, setItems] = useState([])
useEffect(() => {
props.passChildData(Data);
}, [Items])
const handlechange = (e)=>{
setData(e.target.value)
}
const handleSubmit = (e) => {
e.preventDefault();
if (Data === '') {
console.log('enter something');
} else {
setItems([...Items, Data]);
}
}
return (
<div>
<h1>{props.heading}</h1>
<form onSubmit={handleSubmit}>
<input type="text" onChange={handlechange} value={Data}/>
<button type="submit">Add</button>
{Data}
</form>
<div>
{Items.map((item, index) => <div key={index}>{item}</div>)}
</div>
</div>
)
}
我创建了一个fiddle供参考。
问题是您正在改变每个组件中的整个状态。换句话说,你不使用
prevData
。
我会改变 First 和 Second 组件的 onClick
方法的状态,像这样:
setItems((prevData)=>{
const newData = [***...prevData***, ...Items,Data];
props.passChildData(newData)
return newData
})