当我试图过滤从API提取的数据结果时,我得到了一个错误。
当我使用我的searchBar组件过滤redux数据时,当我输入任何东西时,错误消息出现。
下面是错误信息:
"错误:[Immer]一个Immer生产者返回了一个新值和修改了它的草案。返回一个新值或修改草稿。">
我必须做什么来过滤数据并返回新数据?
下面是我正在使用的组件和Redux TK切片。
<<p>Home.js组件/strong>import React, {useState, useEffect} from 'react';
import { Col, Container, Row } from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import { getCountries } from '../redux/search';
// import LazyLoading from 'react-list-lazy-load';
// import { updateText } from '../redux/searchTerm';
import SearchBar from '../components/SearchBar';
import CardComponent from '../components/Card';
import DropdownMenu from '../components/DropdownMenu';
const Home = () => {
const dispatch = useDispatch();
// const [ countries, setCountries ] = useState(null);
const countries = useSelector((state) => state.search);
// const filterCountry = (searchCountry) => {
// countries.list.payload.filter(country => country.name.toLowerCase() == searchCountry.toLowerCase())
// }
useEffect(() => {
dispatch(getCountries());
console.log(countries);
}, [dispatch]);
// console.log(countries.filter(country => country.region.toLowerCase() === 'africa'))
return (
<>
<Container className="home-container">
<Row>
<Col sm={12} md={6} className="left">
<SearchBar />
</Col>
<Col sm={12} md={6} className="right">
<DropdownMenu/>
</Col>
</Row>
<Row className="countryRow">
{ countries.status == 'success'
?<>
{countries.list.map((country) => {
return <CardComponent key={country.name}
title={country.name}
image={country.flags[0]}
population={country.population}
region={country.region}
capital={country.capital}/>
})}
</>
:<div>Loading.....</div>
}
</Row>
</Container>
</>
)
}
export default Home;
SearchBar.js
import React from 'react';
import {useSelector, useDispatch} from 'react-redux';
// import { updateText } from '../redux/searchTerm';
import { searchTerm } from '../redux/search';
const SearchBar = () => {
const query = useSelector((state) => state.searchDefault);
const dispatch = useDispatch();
return (
<>
<form>
<input
className="search"
type="search"
placeholder="Search for a country"
value={query}
onChange={(e) => dispatch(searchTerm(e.target.value))}/>
</form>
</>
)
}
export default SearchBar;
search.js片
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';
export const getCountries = createAsyncThunk(
'searchDefault/getCountries', async () => {
try {
const resp = await axios.get('https://restcountries.com/v2/all');
return await resp.data;
} catch (error) {
console.log(error.message);
}
}
)
const searchSlice = createSlice({
name: 'searchDefault',
initialState: {
list: [],
status: null,
value: ''
},
reducers: {
searchTerm: (state, action) => {
// console.log(state.value);
state.value = action.payload
// console.log(state.value);
state.list.filter( country => country.name == state.value);
return state.list;
// console.log(state.list);
}
},
extraReducers: {
[getCountries.pending]: (state, action) => {
state.status = 'loading'
},
[getCountries.fulfilled]: (state, payload) => {
console.log(payload)
state.list = payload.payload
state.status = 'success'
},
[getCountries.rejected]: (state, action) => {
state.status = 'failed'
}
}
})
export const { searchTerm } = searchSlice.actions;
export default searchSlice.reducer;
根据redux-toolkit的文档:
Redux Toolkit的createReducer API在内部自动使用Immer。因此,"变异"已经是安全的了传递给createReducer的任何case reducer函数内部的状态:
And Immer docs:
还允许从生产者函数返回任意其他数据。但前提是你没有修改草稿
在您的减速器中,您使用immer API来改变值(state.value = action.payload
)并返回结果。但是Immer只允许你做两件事中的一件,不能同时做。所以要么你改变状态
searchTerm: (state, action) => {
state.value = action.payload; // notify redux that only the value property is dirty
}
或者完全替换新状态:
searchTerm: (state, action) => {
return { ...state, value: action.payload }; // replace the whole state
// useful when you need to reset all state to the default value
}
大多数情况下,您只需要告诉redux片的特定属性被更改,然后redux将只通知订阅该属性的组件(通过useSelector
)重新呈现。因此,删除您的reducer中的返回语句,您的代码应该可以再次工作:
searchTerm: (state, action) => {
state.value = action.payload;
state.list = state.list.filter( country => country.name == state.value);
// remove the return statement
}