如何在React.js中使用获取的数据过滤数组?

时间:2019-09-20 14:25:12

标签: javascript reactjs list filter

我正在尝试使用获取的用户列表过滤数组。用户以组件状态存储。我想通过输入中的文本过滤它。

问题:输入字母时,列表正在过滤,但是删除字母时,结果保持不变。

感谢帮助!

class App extends React.Component {
    state = {
        isLoading: true,
        users: [],
        error: null
    }

    fetchUsers() {
        fetch(`https://jsonplaceholder.typicode.com/users`)
        .then(response => response.json())
        .then(data =>
            this.setState({
              users: data,
              isLoading: false,
            })
        )
        .catch(error => this.setState({ error, isLoading: false }));
    }

    componentDidMount() {
        this.fetchUsers();
    }

    onChangeHandler(e) {
        console.log(e.target.value);
        let newArray = this.state.users.filter((d)=>{
            let searchValue = d.name.toLowerCase();
            return searchValue.indexOf(e.target.value) !== -1;
        });
        console.log(newArray)
        this.setState({
            users:newArray
        })
    }

    render() {
        const {isLoading, users, error} = this.state;
            return (
                <div>
                    <h1>Users List</h1>
                    <input type="text" value={this.state.value} placeholder="Search by user name..." onChange={this.onChangeHandler.bind(this)}/>
                    {error ? <p>{error.message}</p> : null}
                    <ol>
                    {!isLoading ? (
                        users.map(user => {
                            const {username, name, id} = user;
                            return (
                                <li key={id}>
                                    <p>{name} <span>@{username}</span></p>
                                </li>
                            );
                        })
                    ) : (
                        <h3>Loading...</h3>
                    )}
                    </ol>
                </div>
            );
      }
}

export default App;

3 个答案:

答案 0 :(得分:0)

发生这种情况是因为您没有跟踪从API获得的原始值。一旦开始对其进行过滤,就会丢失完整列表。

我创建了一个codeandbox:https://codesandbox.io/s/nostalgic-sunset-jig33来解决您的问题。

我要做的是在initialUsers中添加一个state值,并使用它来存储来自API的值:

state = {
    isLoading: true,
    initialUsers: [],
    users: [],
    inputValue: "",
    error: null
  };

 fetchUsers() {
    fetch(`https://jsonplaceholder.typicode.com/users`)
      .then(response => response.json())
      .then(data =>
        this.setState({
          initialUsers: data,
          isLoading: false
        })
      )
      .catch(error => this.setState({ error, isLoading: false }));
  }

render方法中,我通过检查是否在input元素中输入了文本来在显示原始列表的过滤列表之间切换

(!!inputValue ? users : initialUsers).map(
              user => {
                const { username, name, id } = user;
                return (
                  <li key={id}>
                    <p>
                      {name} <span>@{username}</span>
                    </p>
                  </li>
                );
              }
            )

答案 1 :(得分:0)

好吧,如果您从逻辑上看一下当前的解决方案,那么您将遇到以下情况

  • 用户是一个空数组,isLoading为真
  • 将用户提取并推送到数组中,让我们假设['John', 'Joe', 'Alfred']
  • 您为用户过滤字母J,并将用户状态更新为['John', 'Joe']
  • 您删除了字母J的过滤器,并将用户状态更新为['John', 'Joe'],导致组件完全忘记了Alfred,在步骤3中删除了下摆。

因此,您有几种选择,只需在映射之前过滤渲染,具体取决于有多少用户,这不应该那么糟,也可以在状态上创建多个属性,例如filteredUsers,其中包含与您的过滤器匹配的users列表,并改为使用该状态。

关于当前过滤器的一个很酷的事情是,随着结果集的减少,它总是可以更快地运行,所以这是一件好事,但是我怀疑您会与如此之多的用户打交道。

答案 2 :(得分:0)

要达到预期效果,请在使用setState更新用户后,使用以下选项将用户列表从API存储到变量中

apiUsers = [];

    fetchUsers() {
        fetch(`https://jsonplaceholder.typicode.com/users`)
        .then(response => response.json())
        .then(data =>{
        this.apiUsers = data;
            this.setState({
              users: data,
              isLoading: false,
            })
            }
        )
        .catch(error => this.setState({ error, isLoading: false }));
    }

this.state.users中使用新创建的变量-apiUsers代替过滤onChangeHandler

onChangeHandler(e) {
        console.log(e.target.value);
        let newArray = this.apiUsers.filter((d)=>{
          console.log(d)
            let searchValue = d.name.toLowerCase();
            return searchValue.indexOf(e.target.value) !== -1;
        });
        console.log(newArray)
        this.setState({
            users:newArray
        })
    }

工作代码以供参考-https://stackblitz.com/edit/react-sncf1e?file=index.js

问题:state.users数组正在更新,而没有来自api的实际用户列表的副本