Reactjs React Redux-如何进行双重分派
我正在从我的API中获取一些数据,它正常工作。但是当在同一页上进行双重分派时,API就不再工作了。最好用代码来解释它: 服务器:Reactjs React Redux-如何进行双重分派,reactjs,react-redux,Reactjs,React Redux,我正在从我的API中获取一些数据,它正常工作。但是当在同一页上进行双重分派时,API就不再工作了。最好用代码来解释它: 服务器: router.get("/", (req, res) => { let sql = "SELECT * FROM design_categories"; let query = connection.query(sql, (err, results) => { if (err) throw err;
router.get("/", (req, res) => {
let sql = "SELECT * FROM design_categories";
let query = connection.query(sql, (err, results) => {
if (err) throw err;
res.header("Access-Control-Allow-Origin", "*");
res.send(results);
});
});
router.get("/", (req, res) => {
let sql = "SELECT * FROM food_categories";
let query = connection.query(sql, (err, results) => {
if (err) throw err;
res.header("Access-Control-Allow-Origin", "*");
res.send(results);
});
});
他们工作
action.js
export const fetchDesignCat = () => {
setLoading()
return async dispatch => {
const response = await axios
.get("http://localhost:5000/api/designcategories")
.then(results => results.data)
try {
await dispatch({ type: FETCH_DESIGN_CAT, payload: response })
} catch (error) {
console.log("await error", error)
}
}
}
export const fetchFoodCat = () => {
setLoading()
return async dispatch => {
const response = await axios
.get("http://localhost:5000/api/foodcategories")
.then(results => results.data)
try {
await dispatch({ type: FETCH_FOOD_CAT, payload: response })
} catch (error) {
console.log("await error", error)
}
}
}
他们两个都工作得很好
reducer.js
const initalState = {
db: [],
loading: true,
designcat: [],
foodcat: [],
}
export default (state = initalState, action) => {
switch (action.type) {
// different cases
case FETCH_DESIGN_CAT:
return {
designcat: action.payload,
loading: false,
}
case FETCH_FOOD_CAT:
return {
food: action.payload,
loading: false,
}
}
减速器可以完美地更新状态
页面设置.js
const Settings = ({ designcat, foodcat, loading }) => {
const dispatch = useDispatch()
// ... code
useEffect(() => {
dispatch(fetchDesignCat()) // imported action
dispatch(fetchFoodCat()) // imported action
// eslint-disable-next-line
}, [])
// ... code that renders
const mapStateToProps = state => ({
designcat: state.appDb.designcat,
foodcat: state.appDb.foodcat,
loading: state.appDb.loading,
})
export default connect(mapStateToProps, { fetchDesignCat, fetchFoodCat })(
Settings
)
现在问题来了。如果我只使用一个调度,我就可以得到一个或另一个。但是,如果我使用这两种方法,它们看起来就像,如果第二种方法覆盖了第一种方法。这听起来很奇怪
从我的ReduxDevTools
我肯定在什么地方弄错了。有什么想法吗
谢谢 reducer不会将现有状态与新状态合并,这就是为什么每个操作都会替换以前的状态。您需要复制状态的其他属性,并且只替换您的特定操作应该替换的属性。在这里,我使用的是前一个状态的浅拷贝:
export default (state = initalState, action) => {
switch (action.type) {
case FETCH_DESIGN_CAT:
return {
...state, // <----
designcat: action.payload,
loading: false,
}
case FETCH_FOOD_CAT:
return {
...state, // <----
food: action.payload,
loading: false,
}
}
}
代码中还有一个竞争条件,这对您来说可能是问题,也可能不是问题。由于同时启动FETCH_DESIGN_CAT和FETCH_FOOD_CAT,并且它们都在完成后设置loading:false,因此当第一个操作完成时,加载将为false,但另一个操作仍将加载其数据。如果这种情况是已知的,并且是在代码中处理的,例如,如果加载为false,您不相信这两个项都会出现在状态中,那么也可以
解决方案是将这两个类别的获取合并到一个thunk中,或者使用它们自己的加载状态属性为它们创建单独的子缩减器。当然,您也可以手动设置和取消设置加载。您的reducer不会将现有状态与新状态合并,这就是为什么每个操作都会替换以前的状态。您需要复制状态的其他属性,并且只替换您的特定操作应该替换的属性。在这里,我使用的是前一个状态的浅拷贝:
export default (state = initalState, action) => {
switch (action.type) {
case FETCH_DESIGN_CAT:
return {
...state, // <----
designcat: action.payload,
loading: false,
}
case FETCH_FOOD_CAT:
return {
...state, // <----
food: action.payload,
loading: false,
}
}
}
代码中还有一个竞争条件,这对您来说可能是问题,也可能不是问题。由于同时启动FETCH_DESIGN_CAT和FETCH_FOOD_CAT,并且它们都在完成后设置loading:false,因此当第一个操作完成时,加载将为false,但另一个操作仍将加载其数据。如果这种情况是已知的,并且是在代码中处理的,例如,如果加载为false,您不相信这两个项都会出现在状态中,那么也可以
解决方案是将这两个类别的获取合并到一个thunk中,或者使用它们自己的加载状态属性为它们创建单独的子缩减器。当然,您也可以手动设置和取消设置加载。正如您所知,指的是特定的软件工程概念:正如您所知,指的是特定的软件工程概念: