gpt4 book ai didi

javascript - useReducer 返回未定义而不是对象数组

转载 作者:行者123 更新时间:2023-12-05 06:22:58 27 4
gpt4 key购买 nike

为了深入研究 React Hooks,我决定尝试制作 snake 并使用 useReducer/useContext 状态管理。

现在,我被阻止在需要方向键来更改事件图 block 状态的地方。在 useReducer 中,这似乎接收了正确的有效负载,并创建了正确的有效负载对象,但是当它更新状态时它是未定义的?

按向下键会出现“TypeError: Cannot read property 'some' of undefined”的错误,这意味着 snake 是未定义的。

Board.jsx

import React, { useContext, useEffect } from "react";

import Tile from "./Tile.jsx";
import { snakeContext } from '../contexts/snakeContext'

const Board = () => {
const {
state: {
snake, food, direction, gameOver
},
dispatch,
rows,
cols
} = useContext(snakeContext)

useEffect(() => {
const onKeyPress = (e) => {
switch (e.keyCode) {
case 38: //Up
return direction === "down" || dispatch({ type: 'DIRECTION', payload: "up" });
case 40: // Down
return direction === "up" || dispatch({ type: 'DIRECTION', payload: "down" });
case 37: //Left
return direction === "right" || dispatch({ type: 'DIRECTION', payload: "left" });
case 39: // Right
return direction === "left" ||
dispatch({ type: 'DIRECTION', payload: "right" });
default:
break;
}
};
window.addEventListener("keydown", onKeyPress);
return () => window.removeEventListener("keydown", onKeyPress);
}, [direction]);

useEffect(() => {
const interval = setInterval(() => {
switch (direction) {
case "up":
dispatch({ type: 'SNAKE', payload: { ...snake[0], y: snake[0].y - 1 } })
break

case "down":
dispatch({ type: 'SNAKE', payload: { ...snake[0], y: snake[0].y + 1 } })
break;
case "left":
dispatch({ type: 'SNAKE', payload: { ...snake[0], x: snake[0].x - 1 } })
break;
case "right":
dispatch({ type: 'SNAKE', payload: { ...snake[0], x: snake[0].x + 1 } })
break;
default:
break;
}
}, 500);
return () => clearInterval(interval);
});

const style = {
maxHeight: `${2 * rows}rem`,
maxWidth: `${2 * cols}rem`,
margin: "0 auto",
paddingTop: "4rem"
};

const isActiveMatchingState = (i, j) => {
return snake.some(snakeTile =>
snakeTile.y === i && snakeTile.x === j
)
}

const renderBoard = () => {
let grid = Array.from(Array(rows), () => new Array(cols));

for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[i].length; j++) {
grid[i][j] = (
<Tile
isActive={isActiveMatchingState(i, j)}
isFood={food.y === i && food.x === j}
key={`${[i, j]}`}
/>
);
}
}
return grid;
};

return (
gameOver ?
<div>GAME OVER</div> :
<div style={style}>{renderBoard()}</div>
)
};

export default Board;

snakeReducer.jsx

export const snakeReducer = (state, action) => {
const { type, payload } = action;

switch (type) {
case 'SNAKE':
return [{ ...state.snake[0], x: payload.x, y: payload.y }]
case 'FOOD':
return { ...state, x: payload.x, y: payload.y };
case 'DIRECTION':
return { ...state, direction: payload };
case 'GAME_OVER':
return { ...state, gameOver: payload };
default:
throw new Error();
}
};

我的 useContext 设置使用建议的 useMemo - https://hswolff.com/blog/how-to-usecontext-with-usereducer/

蛇语境.js

import React, { createContext, useReducer, useMemo } from 'react';
import { snakeReducer } from '../reducers/snakeReducer';

export const snakeContext = createContext();

const rows = 20;
const cols = 15;

const randomPosition = (biggestNumber) => Math.floor(Math.random() * biggestNumber)

const initialState = {
snake: [{ x: 0, y: 0 }],
food: { x: randomPosition(rows), y: randomPosition(cols) },
direction: null,
gameOver: false
};

const SnakeContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(snakeReducer, initialState);

const contextValue = useMemo(() => ({ state, rows, cols, dispatch }), [state, dispatch]);

return <snakeContext.Provider value={contextValue}>{children}</snakeContext.Provider>;
};

export default SnakeContextProvider;

App.js

import React from 'react';

import Home from './pages/Home';
import SnakeContextProvider from './contexts/snakeContext';
import './App.css';

const App = () => {
return (
<SnakeContextProvider>
<Home />
</SnakeContextProvider>
)
};

export default App;

Home.jsx是包含Board.jsx的页面组件

奇怪的是方向按键的更新更新正常,所以 useReducer 似乎设置正确。

完整的当前 repo 在这里 - https://github.com/puyanwei/snake

谢谢!

最佳答案

最后是我的reducer,'SNAKE'的正确返回应该是;

 case 'SNAKE':
return {
...state,
snake: [{ x: payload.x, y: payload.y }, ...state.snake]
};

感谢所有帮助过的人!

关于javascript - useReducer 返回未定义而不是对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58810087/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com