Как отфильтровать массив с извлеченными данными в React.js? - PullRequest
1 голос
/ 20 сентября 2019

Я пытаюсь отфильтровать массив с выбранным списком пользователей.Пользователи хранятся в состоянии компонента.Я хочу отфильтровать его по тексту из ввода.

Проблема: при вводе писем список фильтруется, но при удалении букв результат остается неизменным.

Спасибо за помощь !!!

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 голосов
/ 20 сентября 2019

Что ж, если вы логически посмотрите на свое текущее решение, то у вас будет следующая ситуация

  • users - пустой массив, с isLoading true
  • пользователи выбираются и помещаются впредположим, что ['John', 'Joe', 'Alfred']
  • вы фильтруете своих пользователей на букву J и обновляете пользовательское состояние до ['John', 'Joe']
  • Вы удаляете фильтр на букву J и обновляетепользовательское состояние ['John', 'Joe'] потому что компонент полностью забыл о Alfred, вы удалили кромку на шаге 3

Итак, у вас есть несколько опций, просто отфильтруйте рендер перед отображением, в зависимости от того, сколькопользователи, которые не должны быть такими плохими или создавать более 1 свойства в состоянии, скажем filteredUsers, которое содержит список users, которые соответствуют вашему фильтру, и работать вместо этого с этим состоянием.

Крутая вещь в вашем текущем фильтре, это то, что он всегда будет работать быстрее, так как ваш набор результатов вроде обрезается, так что это хорошо, но я сомневаюсь, что вы будете иметь дело с таким количеством пользователей, что вам нужнод это.

0 голосов
/ 20 сентября 2019

Для достижения ожидаемого результата используйте нижеприведенную опцию сохранения списка пользователей из API в переменную после использования setState для обновления пользователей

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 in 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

0 голосов
/ 20 сентября 2019

Это происходит потому, что вы не отслеживаете исходные значения, которые вы получаете от API.Как только вы начнете фильтровать его, вы потеряете полный список.

Я создал коды и поле: 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>
                );
              }
            )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...