reactjs useState: select onChange 触发 setState 但组件不重新渲染
reactjs useState: select onChange triggers setState but component doesn't re-render
我正在尝试使用反应中的 select 下拉列表按 属性 对对象数组进行排序。
数据是使用 useState() 挂钩在父容器中定义的,我将 onSortChange 函数向下传递给子 select 组件 DataSelector。数据由另一个组件 DataList 显示为列表。下面要演示的最小示例(为简洁起见减去导入):
- 父容器:
const ParentContainer = () => {
const [data, setData] = useState([]);
useEffect( () => {
populateData();
}, []);
function populateData() {
const dave = {first_name: 'David', last_name: 'Taylor',
age: 25, salary: 25000};
const bob = {first_name: 'Robert', last_name: 'Bush',
age: 31, salary: 30000};
const sue = {first_name: 'Susan', last_name: 'Harman',
age: 22, salary: 28000};
setData([dave, bob, sue])
};
const onSortChange = function(property) {
setData(data.sort(propertySort(property)));
};
// sort by object property value (works for strings or )
const propertySort = (prop) => {
return function(a, b) {
return (a[prop] < b[prop]) ? -1 : (a[prop] > b[prop]) ? 1 : 0;
};
};
return (
<>
<DataSelector onSortChange={onSortChange} />
<DataList data={data}/>
</>
);
};
2:数据选择器组件
const DataSelector = ({onSortChange}) => {
const handleChange = function(event) {
onSortChange(event.target.value);
}
return (
<select onChange={handleChange}>
<option value="first_name">Name</option>
<option value="age">Age</option>
<option value="salary">Salary</option>
</select>
);
};
export default DataSelector;
当我更改 select 选项时,handleChange 会正确触发,如果我 console.log 父容器中的“数据”它会正确 returns 数组按从 handleChange 传递的值排序.但是,DataList 组件不会重新呈现列表项。
在调用数据的 setState 函数后,是否需要采取其他步骤让 DataList 重新呈现?
我认为您需要将数据设置为新的内容,data.sort() 是同一个数组。如果您克隆数据然后将排序后的克隆传递给 setData,我认为它应该可以工作。
我认为您需要使用扩展运算符才能正确更新状态
尝试如下:-
setData([...data.sort(propertySort(property))]);
sort() 方法就地排序数组的项目。除了返回排序后的数组外,它还改变了元素在原始数组中的位置。
因此 setData 不会更改值。使用以下任一方法解决您的问题。
setData(data.slice().sort(propertySort(property)));
或
setData([...data.sort(propertySort(property))]);
或者
setData([...data].sort(propertySort(property)));
我正在尝试使用反应中的 select 下拉列表按 属性 对对象数组进行排序。
数据是使用 useState() 挂钩在父容器中定义的,我将 onSortChange 函数向下传递给子 select 组件 DataSelector。数据由另一个组件 DataList 显示为列表。下面要演示的最小示例(为简洁起见减去导入):
- 父容器:
const ParentContainer = () => {
const [data, setData] = useState([]);
useEffect( () => {
populateData();
}, []);
function populateData() {
const dave = {first_name: 'David', last_name: 'Taylor',
age: 25, salary: 25000};
const bob = {first_name: 'Robert', last_name: 'Bush',
age: 31, salary: 30000};
const sue = {first_name: 'Susan', last_name: 'Harman',
age: 22, salary: 28000};
setData([dave, bob, sue])
};
const onSortChange = function(property) {
setData(data.sort(propertySort(property)));
};
// sort by object property value (works for strings or )
const propertySort = (prop) => {
return function(a, b) {
return (a[prop] < b[prop]) ? -1 : (a[prop] > b[prop]) ? 1 : 0;
};
};
return (
<>
<DataSelector onSortChange={onSortChange} />
<DataList data={data}/>
</>
);
};
2:数据选择器组件
const DataSelector = ({onSortChange}) => {
const handleChange = function(event) {
onSortChange(event.target.value);
}
return (
<select onChange={handleChange}>
<option value="first_name">Name</option>
<option value="age">Age</option>
<option value="salary">Salary</option>
</select>
);
};
export default DataSelector;
当我更改 select 选项时,handleChange 会正确触发,如果我 console.log 父容器中的“数据”它会正确 returns 数组按从 handleChange 传递的值排序.但是,DataList 组件不会重新呈现列表项。
在调用数据的 setState 函数后,是否需要采取其他步骤让 DataList 重新呈现?
我认为您需要将数据设置为新的内容,data.sort() 是同一个数组。如果您克隆数据然后将排序后的克隆传递给 setData,我认为它应该可以工作。
我认为您需要使用扩展运算符才能正确更新状态
尝试如下:-
setData([...data.sort(propertySort(property))]);
sort() 方法就地排序数组的项目。除了返回排序后的数组外,它还改变了元素在原始数组中的位置。
因此 setData 不会更改值。使用以下任一方法解决您的问题。
setData(data.slice().sort(propertySort(property)));
或
setData([...data.sort(propertySort(property))]);
或者
setData([...data].sort(propertySort(property)));