#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
изменении, а не при каждом изменении состояния.