功能组件始终在渲染中使用以前的状态

时间:2020-04-24 13:53:27

标签: reactjs react-hooks

我对使用挂钩和功能组件还很陌生。

我有一个过滤列表。当我尝试更新过滤器时,它将使用上一个过滤器状态,而不是新的状态。我一定会错过一些渲染/状态更改指令,但似乎无法弄清楚它是什么。

我非常感谢我能提供的帮助:)

下面的伪代码:

export default function TransferList(props) {
  const [wholeList, setWholeList] = React.useState([]);
  const [filteredList, setFilteredList] = React.useState([]);
  const [filter, setFilter] = React.useState([]);

  return (
    <>
      <TextField
        value={filter}
        onChange={(e) => {
          // Set filter input
          setFilter(e.target.value);

          // Filter the list
          let filtered = wholeList.filter(
            (item) => item.indexOf(filter) !== -1
          );
          setFilteredList(filtered);
        }}
      />

      <List>
        {filteredList.map((item) => (
          <ListItem>Item: {item}</ListItem>
        ))}
      </List>
    </>
  );
}

4 个答案:

答案 0 :(得分:1)

在onChange内,您应该使用将值保存为常量,filter不会在setFilter(filterValue)之后更新,因为这是异步操作。

<TextField
  value={filter}
  onChange={e => {
    const filterValue = e.target.value;
    // Set filter input
    setFilter(filterValue);

    // Filter the list
    let filtered = wholeList.filter(item => item.indexOf(filterValue) !== -1);
    setFilteredList(filtered);
  }}
/>;

答案 1 :(得分:1)

状态更新是异步的,因此过滤器状态更新不会立即反映后缀

您必须存储新的过滤器值并根据该值设置状态

export default function TransferList(props) {

    const [wholeList, setWholeList] = React.useState([]);
    const [filteredList, setFilteredList] = React.useState([]);
    const [filter, setFilter] = React.useState([]);

    return (
        <>
            <TextField value={filter} onChange={(e) => {
                // Set filter input
                const newFilter = e.target.value;
                setFilter(newFilter)

                // Filter the list
                let filtered = wholeList.filter(item => item.indexOf(newFilter) !== -1)
                setFilteredList(filtered)
            }} />

            <List>
                {filteredList.map(item => <ListItem>Item: {item}</ListItem>)}
            </List>
        </>
    )
}

答案 2 :(得分:0)

因此,事实证明,我必须首先将整个未过滤列表提供给初始过滤列表。由于某种原因可以解决此问题。

const [filteredList, setFilteredList] = React.useState(props.wholeList);

最初,我希望一个空的过滤器不显示任何内容,但是当过滤器为空时,我可能不得不解决显示整个列表的问题

答案 3 :(得分:0)

命令您的代码提高可读性

使用简洁代码

主要更改:

  • 使用解构代替道具
  • 从html返回中删除jsx以提高可读性
  • 使用include代替indexOf
  • 将密钥添加到列表

    export default function TransferList({ wholeList }) {
    
      const [filteredList, setFilteredList] = React.useState(wholeList);
      const [filter, setFilter] = React.useState([]);
    
      const handleOnChange = ({ target }) => {
        setFilter(target.value);
        const updatedFilteredList = wholeList.filter(item => item.includes(target.value));
        setFilteredList(updatedFilteredList);
      }
    
      const list = filteredList.map(item => {
        return <ListItem key={item}>Item: {item}</ListItem>
      });
    
      return (
        <>
          <TextField value={filter} onChange={handleOnChange} />
          <List>{list}</List>
        </>
      );
    }
    

我有一个过滤器组件,可以在其中执行过滤器列表。

import React, { useState } from 'react';

function FilterInput({ list = [], filterKeys = [], placeholder = 'Search',
  onFilter }) {

  const [filterValue, setFilterValue] = useState('');

  const updateFilterValue = ev => {
    setFilterValue(ev.target.value);
    const value = ev.target.value.toLowerCase();
    if (!value) onFilter(list);
    else {
      const filteredList = list.filter(item => filterKeys.some(key => item[key].toLowerCase().includes(value)));
      onFilter(filteredList);
    }
  }

  return (
    <input className="filter-input" type="text" placeholder={placeholder}
      value={filterValue} onChange={updateFilterValue} />
  );
}

export default FilterInput;

来自父组件的调用看起来像这样

<FilterInput list={countries} filterKeys={['name']} placeholder="Search Country"
          onFilter={filterCountries} />

这是在我的电晕应用程序中。您可以在我的Github上查看。

看看我如何构建过滤器

https://github.com/omergal99/hello-corona