ReactJs 管理一组有状态组件
ReactJs managing an array of stateful components
我有一个父组件,我想用它来动态添加和删除有状态组件,但是发生了一些奇怪的事情。
这是我的父组件以及我如何控制 FilterBlock
的列表
import React from 'react'
import FilterBlock from './components/FilterBlock'
export default function List() {
const [filterBlockList, setFilterList] = useState([FilterBlock])
const addFilterBlock = () => {
setFilterList([...filterBlockList, FilterBlock])
}
const onDeleteFilterBlock = (index) => {
const filteredList = filterBlockList.filter((block, i) => i !== index);
setFilterList(filteredList)
}
return (
<div>
{
filterBlockList.map((FilterBlock, index) => (
<FilterBlock
key={index}
onDeleteFilter={() => onDeleteFilterBlock(index)}
/>
))
}
<button onClick={addFilterBlock}></button>
</div>
)
}
您可以假设 FilterBlock
是一个有状态的 React Hooks 组件。
我的问题是,每当我从任何添加的组件内部触发 onDeleteFilter
时,只有最后推送的 FilterBlock
会从列表中删除,即使我根据它在列表。
请在此处查看我的示例:
问题是您将组件函数 FilterBlock
存储到状态并改变子组件内的父状态。
您可能知道直接改变状态会导致意想不到的错误。你在这里改变状态:
/* Child component */
function FilterBlock(props) {
const [value, setValue] = React.useState('')
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
const onInputChange = (e) => {
// child state has been changed, but parent state
// does not know about it
// thus, parent state has been mutated
setValue(e.target.value)
}
return (
<div>
<button onClick={props.onDeleteFilter}>remove</button>
<input value={value} onChange={onInputChange}></input>
</div>
)
}
/* Parent component */
const addFilterBlock = () => {
setFilterList([...filterBlockList, FilterBlock])
}
filterBlockList.map((FilterBlock, index) => (
<FilterBlock
key={index}
onDeleteFilter={() => onDeleteFilterBlock(index)}
/>
))
当 FilterBlock 值发生变化时,FilterBlock
会将其状态存储在 List
组件无法控制的地方。这意味着 filterBlockList
状态已发生变异。这会导致无法预测的错误,如上述问题。
为了克服这个问题,你需要在父组件中管理整个状态:
const {useCallback, useState} = React;
function FilterBlock(props) {
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
return (
<div>
<button onClick={props.onDeleteFilter}>remove</button>
<input value={props.value} onChange={props.onChange}></input>
</div>
)
}
function App() {
const [values, setValues] = useState(['strawberry']);
const addFilterBlock = useCallback(() => {
setValues(values.concat(''));
}, [values]);
const onDeleteFilterBlock = useCallback((index) => {
setValues(values.filter((v, i) => i !== index));
}, [values]);
const setFilterValue = useCallback((index, value) => {
const newValues = [...values];
newValues[index] = value;
setValues(newValues);
}, [values]);
return (
<div>
{
values.map((value, index) => (
<FilterBlock
key={index}
onDeleteFilter={() => onDeleteFilterBlock(index)}
value={value}
onChange={(e) => setFilterValue(index, e.target.value)}
/>
))
}
<button onClick={addFilterBlock}>add</button>
</div>
)
}
ReactDOM.render(<App />, document.querySelector("#app"))
我有一个父组件,我想用它来动态添加和删除有状态组件,但是发生了一些奇怪的事情。
这是我的父组件以及我如何控制 FilterBlock
import React from 'react'
import FilterBlock from './components/FilterBlock'
export default function List() {
const [filterBlockList, setFilterList] = useState([FilterBlock])
const addFilterBlock = () => {
setFilterList([...filterBlockList, FilterBlock])
}
const onDeleteFilterBlock = (index) => {
const filteredList = filterBlockList.filter((block, i) => i !== index);
setFilterList(filteredList)
}
return (
<div>
{
filterBlockList.map((FilterBlock, index) => (
<FilterBlock
key={index}
onDeleteFilter={() => onDeleteFilterBlock(index)}
/>
))
}
<button onClick={addFilterBlock}></button>
</div>
)
}
您可以假设 FilterBlock
是一个有状态的 React Hooks 组件。
我的问题是,每当我从任何添加的组件内部触发 onDeleteFilter
时,只有最后推送的 FilterBlock
会从列表中删除,即使我根据它在列表。
请在此处查看我的示例:
问题是您将组件函数 FilterBlock
存储到状态并改变子组件内的父状态。
您可能知道直接改变状态会导致意想不到的错误。你在这里改变状态:
/* Child component */
function FilterBlock(props) {
const [value, setValue] = React.useState('')
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
const onInputChange = (e) => {
// child state has been changed, but parent state
// does not know about it
// thus, parent state has been mutated
setValue(e.target.value)
}
return (
<div>
<button onClick={props.onDeleteFilter}>remove</button>
<input value={value} onChange={onInputChange}></input>
</div>
)
}
/* Parent component */
const addFilterBlock = () => {
setFilterList([...filterBlockList, FilterBlock])
}
filterBlockList.map((FilterBlock, index) => (
<FilterBlock
key={index}
onDeleteFilter={() => onDeleteFilterBlock(index)}
/>
))
当 FilterBlock 值发生变化时,FilterBlock
会将其状态存储在 List
组件无法控制的地方。这意味着 filterBlockList
状态已发生变异。这会导致无法预测的错误,如上述问题。
为了克服这个问题,你需要在父组件中管理整个状态:
const {useCallback, useState} = React;
function FilterBlock(props) {
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
return (
<div>
<button onClick={props.onDeleteFilter}>remove</button>
<input value={props.value} onChange={props.onChange}></input>
</div>
)
}
function App() {
const [values, setValues] = useState(['strawberry']);
const addFilterBlock = useCallback(() => {
setValues(values.concat(''));
}, [values]);
const onDeleteFilterBlock = useCallback((index) => {
setValues(values.filter((v, i) => i !== index));
}, [values]);
const setFilterValue = useCallback((index, value) => {
const newValues = [...values];
newValues[index] = value;
setValues(newValues);
}, [values]);
return (
<div>
{
values.map((value, index) => (
<FilterBlock
key={index}
onDeleteFilter={() => onDeleteFilterBlock(index)}
value={value}
onChange={(e) => setFilterValue(index, e.target.value)}
/>
))
}
<button onClick={addFilterBlock}>add</button>
</div>
)
}
ReactDOM.render(<App />, document.querySelector("#app"))