我在编写一个带有几个文本框的过滤器组件时遇到了这个问题,它允许用户将列表中的项目限制在另一个组件中。我在 Redux 状态下跟踪我的过滤项目。该解决方案本质上是@Rajnikant 的解决方案;带有一些示例代码。
由于关注,我收到了警告。注意渲染函数中的props.setFilteredItems。
import {setFilteredItems} from './myActions';
const myFilters = props => {
const [nameFilter, setNameFilter] = useState('');
const [cityFilter, setCityFilter] = useState('');
const filterName = record => record.name.startsWith(nameFilter);
const filterCity = record => record.city.startsWith(cityFilter);
const selectedRecords = props.records.filter(rec => filterName(rec) && filterCity(rec));
props.setFilteredItems(selectedRecords); // <-- Danger! Updates Redux during a render!
return <div>
<input type="text" value={nameFilter} onChange={e => setNameFilter(e.target.value)} />
<input type="text" value={cityFilter} onChange={e => setCityFilter(e.target.value)} />
</div>
};
const mapStateToProps = state => ({
records: state.stuff.items,
filteredItems: state.stuff.filteredItems
});
const mapDispatchToProps = { setFilteredItems };
export default connect(mapStateToProps, mapDispatchToProps)(myFilters);
当我使用 React 16.12.0 运行此代码时,我在浏览器控制台中收到了此线程主题中列出的警告。根据堆栈跟踪,有问题的行是我在渲染函数中的props.setFilteredItems 调用。所以我简单地将过滤器调用和状态更改包含在useEffect 中,如下所示。
import {setFilteredItems} from './myActions';
const myFilters = props => {
const [nameFilter, setNameFilter] = useState('');
const [cityFilter, setCityFilter] = useState('');
useEffect(() => {
const filterName = record => record.name.startsWith(nameFilter);
const filterCity = record => record.city.startsWith(cityFilter);
const selectedRecords = props.records.filter(rec => filterName(rec) && filterCity(rec));
props.setFilteredItems(selectedRecords); // <-- OK now; effect runs outside of render.
}, [nameFilter, cityFilter]);
return <div>
<input type="text" value={nameFilter} onChange={e => setNameFilter(e.target.value)} />
<input type="text" value={cityFilter} onChange={e => setCityFilter(e.target.value)} />
</div>
};
const mapStateToProps = state => ({
records: state.stuff.items,
filteredItems: state.stuff.filteredItems
});
const mapDispatchToProps = { setFilteredItems };
export default connect(mapStateToProps, mapDispatchToProps)(myFilters);
当我第一次添加useEffect 时,我将堆栈顶部从堆栈中炸开,因为每次调用useEffect 都会导致状态更改。我必须添加一组跳过效果,这样效果只会在过滤器字段本身发生变化时运行。