我正在React React中构建一个问答游戏,并使用Redux-Thunk来存储一个在游戏开始时创建的游戏对象。
它存储以下内容:
redux-thunk的问题在于处理不同的游戏模式和逻辑。
使用这样的游戏类是一种好习惯吗?
class Game {
constructor() {
Object.assign(this, DEFAULT_STATE);
}
init = (gamemode, players) => {
// set Gamemode
switch (gamemode) {
case "classic":
this.gamemode = new Classic();
break;
}
// set Players
this.players = players;
// set Gameparameters
this.parameters = this.gamemode.getGameParameters();
// set Questions
this.questions = this.gamemode.prepareQuestions();
};
// Getters
getPlayerCount = () => this.players.length;
getCurrentRound = () => this.currentRound + 1;
getCurrentRoundIndex = () => this.currentRound;
}
并通过Context API在提供者中共享它以访问其状态和功能?
答案 0 :(得分:1)
这是一个非常广泛的问题。我将就如何处理这种情况发表自己的看法。
自从React 16.3起,我发现内置的上下文api比Redux更易于使用,功能更强大。这就是我设置上下文提供程序的方式:
const DEFAULT_STATE = {
gameMode: 'default',
players: [],
currentRound: 1,
...
};
export const MyContext = React.createContext(DEFAULT_STATE);
export const MyConsumer = MyContext.Consumer;
class MyProvider extends Component {
state = DEFAULT_STATE;
componentDidMount() {
// query your api on app start here
}
render() {
return (
<MyContext.Provider
value={{
state: this.state,
setState: (name, value, callback = () => {}) => {
this.setState({ [name]: value }, callback);
},
incrementRound: () => {
const { currentRound } = this.state;
this.setState({ currentRound: currentRound + 1 });
},
// any other functions you want to expose to your consumer
}}
>
{this.props.children}
</MyContext.Provider>
}
};
export default MyProvider;
然后您可以像这样设置您的根组件:
ReactDOM.render(
<MyProvider><App /></MyProvider>,
document.getElementById('root')
);
然后,您可以在任何其他组件中访问上下文/消费者:
class SomeComponent extends Component {
state = {/* component state */};
incrementRound = (context) => {
// option a: access state directly
const { currentRound } = context.state;
context.setState('currentRound', currentRound + 1);
// option b: expose function to handle state
context.incrementState();
};
render() {
return (
<section>
<div>{/* some other stuff */}</div>
<MyConsumer>
{context => {
const { currentRound } = context.state;
return (
<div>{currentRound}</div>;
<button>Click to update round!</button>
);
}}
</MyConsumer>
</section>
);
}
}
这是一个非常简单的示例,但我认为这很重要。如果您走这条路线,我还建议您从DEFAULT_STATE
对象中导出状态密钥,这样就不必使用文字字符串调用setState
。您可以执行以下操作:
const stateKeysObj = {};
Object.keys(DEFAULT_STATE).forEach(key => {
stateKeysObj[key] = key;
});
export const stateKeys = Object.freeze(stateKeysObj);
祝你游戏好运!