我正在尝试向数据添加排序功能,但是我遇到了一些问题,我决定尝试使用React钩子,并且不确定我是否做错了什么,问题是当我通过以下方式选择一些值时选择,然后事件状态已更改,页面上没有差异,当我第二次单击另一个值(如果我单击相同的元素则没有任何变化)后,一切便开始正常工作,并且每次单击某个值时,应用了不同的排序方式。为什么从一开始就不想正常工作?
编辑: 首先,在父组件中,我获取数据,然后通过道具:
父母:
const [data, setData] = useState("")
useEffect(() => getDeviceDataTotal(), [])
const getDeviceDataTotal = () => {
console.log('refresh clicked')
fetch("http://localhost:4000/device")
.then(res => res.json())
.then((res) => setData(res))
.catch(err => {
throw err;
});
};
<Route
exact
path="/"
render={() => <Dashboard classes={classes} data={data} refresh={getDeviceDataTotal}/> }
/>
子组件:
function Dashboard(props) {
const [selectedSort, setSelectedSort] = useState("1")
const [devices, setDevices] = useState(props.data)
useEffect(() => {
props.refresh();
setDevices(props.data)
},[devices])
useEffect(() => sortDeviceData(), [selectedSort])
const sortDeviceData = () => {
console.log(devices)
switch(selectedSort) {
case "device":
console.log(devices)
props.data.sort(function(a,b) {
return (a.device_id.toUpperCase() < b.device_id.toUpperCase()) ? -1 : (a.device_id.toUpperCase() > b.device_id.toUpperCase()) ? 1 : 0
})
setDevices(props.data)
break;
case "customer":
props.data.sort(function(a,b) {
return (a.customer.toUpperCase() < b.customer.toUpperCase()) ? -1 : (a.customer.toUpperCase() > b.customer.toUpperCase()) ? 1 : 0
})
setDevices(props.data)
break;
case "server":
props.data.sort(function(a,b) {
return (a.server.toUpperCase() < b.server.toUpperCase()) ? -1 : (a.server.toUpperCase() > b.server.toUpperCase()) ? 1 : 0
})
setDevices(props.data)
break;
case "creation":
props.data.sort(function(a,b) {
return (a.createdAt.toUpperCase() < b.createdAt.toUpperCase()) ? -1 : (a.createdAt.toUpperCase() > b.createdAt.toUpperCase()) ? 1 : 0
})
setDevices(props.data)
break;
case "update":
props.data.sort(function(a,b) {
return (a.updatedAt.toUpperCase() < b.updatedAt.toUpperCase()) ? -1 : (a.updatedAt.toUpperCase() > b.updatedAt.toUpperCase()) ? 1 : 0
})
setDevices(props.data)
break;
default:
return setDevices(props.data)
}
}
<div>
<FormControl className={classes.selectContainer}>
<Select
value={selectedSort}
style={{position: 'absolute', right: 0, bottom: 10, width: 150}}
onChange={e => setSelectedSort(e.target.value)}
>
<MenuItem value="1">Sort</MenuItem>
<MenuItem value="device">Device</MenuItem>
<MenuItem value="customer">User</MenuItem>
<MenuItem value="server">Server</MenuItem>
<MenuItem value="creation">Creation date</MenuItem>
<MenuItem value="update">Update date</MenuItem>
</Select>
</FormControl>
</div>
<div>
<DeviceList
classes={classes}
deviceData={devices ? devices: props.data}
filtered={props.filtered}
/>
</div>
答案 0 :(得分:1)
您的刷新更改props异步,因此在useEffect props.data中仍然为null或您赋予它的任何初始值。 然后,在设置props.data时(根据刷新时解析的承诺),将重新呈现组件。但是由于设备未更改,所以useEffect不会再次执行,并且设备永远不会从props.data中设置为新值。
我建议您确定是否由父级控制来获取数据,然后可以将设备传递到此组件中,或者由该组件进行获取,然后可以使用从状态设置器刷新替换setData的代码。在useEffect中的该组件:
useEffect(() => {
fetch(....
.then(json => setDevices(json.devices)
}, [])
此操作将在第一次渲染时运行一次,并且数据触发将随设备一起重新渲染。
为避免devices.sort不是函数,请添加防护:if(devices)...
答案 1 :(得分:0)
只需将sortDeviceData用作selectedSort的函数,然后将selectedSort传递给:
const sortDeviceData = selectedSort => {...}
由于您的useEffect中未使用selectedSort,因此不会执行该操作。
答案 2 :(得分:0)
好吧,也许我不太确定发生了什么。我假设您最初是从props.data获得设备的?
然后您可以通过在useState的props.data中使用设备来省略第一个useEffect:
const [devices, setDevices] = useState(props.data)
然后,当您更改排序顺序时,不应就位更新props.data-props应该是只读的!
就给定的selectedSort,我个人会编写一个函数返回比较器:
const comparator = selector => {
switch (selector) {
case „1“: return (a,b)=>...
...
}
}
然后做
useEffect(() => setDevices(devices.sort(comparator(selectedSort)))
, [selectedSort])
答案 3 :(得分:0)
您正在获取孩子中的数据,该数据在父级中设置状态。您将此作为数据传递给您的孩子。但是随后您在异步的useEffect中调用了刷新,因此您再次设置了旧的props.data。
在您刷新的孩子中删除useEffect,并将props.data作为设备的useState的初始属性。
可以删除仪表板的刷新属性。
您的父母控制着数据的获取,因此请依靠父母来做。