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

Reactjs 反应挂钩,在选择上设置状态,reactjs,select,react-hooks,Reactjs,Select,React Hooks,我试图给我的数据添加排序功能,但我有一些问题,我决定尝试使用React钩子,但不确定我是否做错了什么,问题是当我通过选择选择某个值时,即使状态已更改,页面上也没有差异,在我第二次单击另一个值后,如果我单击同一个元素,则没有任何更改,然后一切开始正常工作,每次单击某个值,都会应用不同的排序方式。为什么从一开始它就不想正常工作 编辑: 首先在父组件中获取数据,然后通过道具传递数据: 家长: const [data, setData] = useState("") useEffect(() =&

我试图给我的数据添加排序功能,但我有一些问题,我决定尝试使用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>

只需将sortDeviceData设置为selectedSort的函数,并将selectedSort传入:

const sortDeviceData = selectedSort => {...}

由于您的useEffect中未使用selectedSort,因此不会执行它。

好的,可能我不太确定发生了什么。我想你是从道具数据中得到这些设备的吧

然后,您可以在设备的useState中使用props.data来省略第一个useEffect:

const [devices, setDevices] = useState(props.data)
然后,当您更改排序顺序时,不应该更新props.data inplace-props应该是只读的

我个人会编写一个函数,在给定selectedSort的情况下返回比较器:

const comparator = selector => {
  switch (selector) {
    case „1“: return (a,b)=>...
    ...
  }
}
然后呢

useEffect(() => setDevices(devices.sort(comparator(selectedSort)))
  , [selectedSort])

您的刷新会异步更改道具,因此在useEffect props.data中仍然为null或任何初始值。 然后,当从refresh中的已解析承诺设置props.data时,将重新提交组件。但由于设备保持不变,useEffect不会再次执行,并且设备将永远不会被设置为props.data中的新值

我建议您决定是否由父级控制获取数据,然后您可以将设备传递到此组件,或者此组件进行获取,然后您可以在useEffect中使用此组件中的状态设置器刷新替换setData中的代码:

useEffect(() => {
  fetch(....
    .then(json => setDevices(json.devices)
}, [])
这将在第一次渲染时运行一次,并在数据触发器到达时使用设备重新渲染


为了避免使用devices.sort不是一个函数,请添加一个保护:如果设备…

您正在获取子设备中的数据,这将在父设备中设置状态。您可以将其作为数据传递给您的孩子。但是,然后在useffect中调用refresh,这是异步的,因此您需要再次设置旧的props.data

在刷新的子对象中删除useEffect,并使用props.data作为设备useState的初始道具

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


您的家长控制数据获取,因此请依靠家长来完成。

我认为最好使用switch。。。如果条件大于多个,请尝试将“选择”中的属性值更改为默认值,然后重试check@AkhilAravind,关于switch,实际上是真的,我忘了我可以用它了,我已经重写了它来切换,关于defaultValue,它不起作用,你有一个同样的stackblitz示例吗,您对selectedSort使用的是什么软件包?但在useEffect中,我使用selectedSort作为一个需要观察的参数,因此如果selectedSort发生更改,useEffect应该会看到它并进行更新。将selectedSort作为一个参数传递会使它完全不起作用。不幸的是,编辑您的帖子时,它不想添加道具。刷新并单击您的帖子而不是我的。。。不管怎么说,问题可能出在其他地方>我的意思是,当我试图按照你的方式做时,它说device.sort不是一个函数,问题是const[devices,setDevices]=useStateprops.data不会更新设备,它总是空的,同样我以前的useffects似乎也不会对设备的状态产生任何影响。只有在我点击Select two Times中的一些值之后,它才会改变如果我没有错,我按照你说的做了所有这些,我获取它并在componentDidMount瞬间启动它,使用useEffect,然后数据应该被获取并通过道具传递给子组件,由于此时子组件应该通过排序函数更改数据,并基于更改初始化刷新函数。我编辑了我的问题,以澄清我的代码中发生的一切。它起作用了!最后我把你所有的想法都弄混了,加了一点我自己的想法,效果很好,现在我必须清理一个代码,因为我弄乱了一些东西,但最重要的是,这个目标已经实现,现在只是在润色代码:非常感谢你的帮助!