反应挂钩,在选择时设置状态

时间:2019-08-13 10:20:42

标签: reactjs select react-hooks

我正在尝试向数据添加排序功能,但是我遇到了一些问题,我决定尝试使用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>

4 个答案:

答案 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的初始属性。

可以删除仪表板的刷新属性。

您的父母控制着数据的获取,因此请依靠父母来做。