Передача отфильтрованного списка брату или сестре с использованием React.Стиль компонента

#reactjs

#reactjs

Вопрос:

У функции приложения ниже есть метод ‘filteredUsers’, который выполняется каждый раз при выполнении прохода, поэтому, когда задано состояние поиска, он фактически запускает метод, и его результат передается в качестве поддержки функциональному компоненту ‘List’, и все хорошо. Как мне изменить это на более старый стиль React.Компонент, так что это все еще работает? (согласно моей попытке ниже)

 const App = () => {
    const [text, setText] = React.useState('');
    const [search, setSearch] = React.useState('');

    const handleText = (event) => {
        setText(event.target.value);
    };

    const handleSearch = () => {
        setSearch(text);
    };

    console.log('*** App ***');         // each time as I type this is shown

    const filteredUsers = users.filter((user) => {
        console.log('Filter function is running ...');      // each time this is shown
        return user.name.toLowerCase().includes(search.toLowerCase());
    });

    return (
        <div>
            <input type="text" value={text} onChange={handleText} />
            <button type="button" onClick={handleSearch}>
                Search
            </button>

            <List list={filteredUsers} />
        </div>
    );
};

const List = ({ list }) => {
    return (
        <ul>
            {list.map((item) => (
                <ListItem key={item.id} item={item} />
            ))}
        </ul>
    );
};

const ListItem = ({ item }) => {
    return <li>{item.name}</li>;
};

  

Затем в этом реагируйте.Эквивалент компонента (App3) Я пытаюсь это:
Теперь, как мне передать отфильтрованный список компоненту списка при нажатии кнопки поиска?

 class App3 extends React.Component {
    state = {
        text: '',
        search: '',
    }
    handleText(event) {
        this.setState({ text: event.target.value });
    }
    handleSearch() {
        this.setState({ search: this.state.text });
    }
    filteredUsers = users.filter((user) => {
        console.log('Filter function is running ...');
        return user.name.toLowerCase().includes(this.state.search.toLowerCase());
    });
    render() {
        return (
            <div>
                <input type="text" value={this.state.text} onChange={this.handleText.bind(this)} />
                <button type="button" onClick={this.handleSearch.bind(this)}>
                    Search
                </button>

                <List list={this.filteredUsers} />
            </div>
        )
    }
}
  

Ответ №1:

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

В вашей второй версии (class component) эта переменная не обновляется. Итак, вы можете сделать это функцией и вызвать ее для передачи list реквизита:

 filteredUsers = () => // make function
  users.filter((user) => {
    console.log("Filter function is running ...");
    return user.name.toLowerCase().includes(this.state.search.toLowerCase());
  });

render() {
  return (
    <div>
      <input
        type="text"
        value={this.state.text}
        onChange={this.handleText.bind(this)}
      />
      <button type="button" onClick={this.handleSearch.bind(this)}>
        Search
      </button>

      <List list={this.filteredUsers()} /> // invoke
    </div>
  );
}
  

или вы можете переместить его в render метод и присвоить переменной:

 render() {
  const filteredUsers = users.filter((user) => {
    console.log("Filter function is running ...");
    return user.name.toLowerCase().includes(this.state.search.toLowerCase());
  });

  return (
    <div>
      <input
        type="text"
        value={this.state.text}
        onChange={this.handleText.bind(this)}
      />
      <button type="button" onClick={this.handleSearch.bind(this)}>
        Search
      </button>

      <List list={filteredUsers} />
    </div>
  );
}
  

Хотя, если это не обязательно, вам следует использовать первую версию, поскольку компоненты класса больше не подходят для нового компонента.

Вот версия с useMemo :

 const filteredUsers = React.useMemo(
  () =>
    users.filter((user) => {
      console.log("Filter function is running ..."); // each time this is shown
      return user.name.toLowerCase().includes(search.toLowerCase());
    }),
  [search]
);
  

В этом случае эта переменная вычисляется только при search изменении, а не при каждом изменении состояния.