EDIT:为了获得完整的参考,我试图用Redux 来做这件事
https://codesandbox.io/s/github/SenBoyer/codm-tracker-unfinished
快速视觉参考:
https://jsfiddle.net/59r31Lmt/
我试着让它在你点击一个迷彩方块时变成活动的,当你点击所有迷彩方块,金色解锁,当你解锁所有枪支的金色时,钻石";解锁"/变得对所有人都很活跃。
这是我正在使用的切片
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
sandIsActive: false,
jungleIsActive: false,
splinterIsActive: false,
tigerIsActive: false,
dragonIsActive: false,
reptileIsActive: false,
goldIsActive: false,
diamondIsActive: false,
};
const camoBarSlice = createSlice({
name: "camoBar",
initialState,
reducers: {
setSandActive: (state, action) => {
return {
...state,
sandIsActive: !state.isActive,
};
},
setJungleActive: (state, action) => {
return {
...state,
jungleIsActive: !state.isActive,
};
},
setSplinterActive: (state, action) => {
return {
...state,
splinterIsActive: !state.isActive,
};
},
setTigerActive: (state, action) => {
return {
...state,
tigerIsActive: !state.isActive,
};
},
setDragonActive: (state, action) => {
return {
...state,
dragonIsActive: !state.isActive,
};
},
setReptileActive: (state, action) => {
return {
...state,
reptileIsActive: !state.isActive,
};
},
setGoldActive: (state, action) => {
return {
...state,
goldIsActive: !state.isActive,
};
},
},
});
所以当
sandIsActive: true,
jungleIsActive: true,
splinterIsActive: true,
tigerIsActive: true,
dragonIsActive: true,
reptileIsActive: true,
setGoldActive((运行并:
goldIsActive: true
然后,当goldIsActive对所有20支枪都为true时,setDiamondActive((运行并:
diamondIsActive: true
每支枪。
我如何在所有枪之间共享状态逻辑,以便在它们都变为活动时知道运行函数setDiamondActive?
我必须用相同的逻辑为每把枪制作一个单独的切片吗?然后呢?如何传递逻辑?
我是否必须为整个网站上的每个正方形添加一个状态值,因为不可能在其他切片之间共享状态值?你需要把它都放在一片里吗?所以它必须是这样的:
const initialState = {
ak47SandIsActive: false,
ak47JungleIsActive: false,
ak47SplinterIsActive: false,
ak47TigerIsActive: false,
ak47DragonIsActive: false,
ak47ReptileIsActive: false,
ak47GoldIsActive: false,
ak47DiamondIsActive: false,
m13SandIsActive: false,
m13JungleIsActive: false,
m13SplinterIsActive: false,
m13TigerIsActive: false,
m13DragonIsActive: false,
m13ReptileIsActive: false,
m13GoldIsActive: false,
m13DiamondIsActive: false,
};
然后在每个方块上设置一个onClick,并执行相关的调度操作?
我可以把一片放在另一片里面吗?这样我就可以有一个";外减速器";控制菱形方块,而内部减速器控制整个枪逻辑?有什么接近或可以完成同样的事情吗?
基本上,我如何使用redux来跟踪这里的状态?我发布的切片中的逻辑一次只适用于一支枪,但我如何使用它来控制这里20多支枪的逻辑?
我将对您的代码做一些假设:
- 您想知道每个枪何时处于活动状态
- 您想知道某些枪支何时处于活动/非活动状态
- 这些枪支的状态之间有着复杂的相互作用
为此,我的建议是将所有内容合并到一个切片中。如果您需要访问另一个切片中的一个切片的数据,那么,实际上,这是一个切片,因为范围是相同的。将切片视为范围。
首先,我们需要一个函数来确定diamond
何时应该打开:
export const isDiamondActive = (state) => {
const targetKeys = ['sand', 'jungle', reptile'...];
targetKeys.forEach(targetKey => {
if(state[targetKey] === false) {
return false;
}
}
return true;
}
这个函数简单地循环所有的键,如果它们都是true
,则应该告诉我们diamond
也应该是活动的。记住这个功能。
此外,使用RTK,您不再需要担心复制";过去状态";就像你对Redux所做的那样。只要写下你的逻辑,不要去想,所以:
setReptileActive: (state, action) => {
return {
...state,
reptileIsActive: !state.isActive,
};
},
变为:
setReptileActive: (state, action) => {
state[reptileIsActive] = !state[reptileIsActive];
},
或者,更好的是,删除上面所有的reducer,并在一个函数中重构它:
toggledGunStatus: (state, action) => {
const { id } = action;
//If the did we were provided isn't in the state, stop.
if(!(id in state)) {
return;
}
state[id] = !state[id];
}
考虑到所有这些,我们有两个选择。我认为isDiamondActive
的检查应该在toggleGunStatus
减速器内部进行,因为它们紧密地联系在一起。所以,一个简单的:
const diamondActive = isDiamondActive(state);
if(diamondActive) {
state['diamond'] = diamondActive;
}
然而,当我们谈论复杂逻辑时,事情可能会变得一团糟,因此,也许您希望为此设置一个侦听器中间件——它只需侦听toggledGunStatus
操作,并作为响应,进一步运行isDiamondActive
检查和调度/更改状态。
顺便说一句,我觉得你的系统会更复杂一些。每把枪都会保存大量数据,而不仅仅是isActive
标志。考虑一下实体适配器,它为项目集合提供了预构建的CRUD操作。从本质上讲,切片应该是一组对象,其中每个对象都是一把枪。如果你使用的是TS,你可以优雅地将所有这些定义为:
export type Gun = {
id: string;
isActive: boolean;
}
export const entityAdapter = createEntityAdapter<Gun>();
..
const initialState: InitialState /* complex, can ignore */ = {
guns: entityAdapter.getInitialState();
}
现在,每当你使用选择器时,你都在使用一个集合。更干净;未来证明";。