React Reducer (useReducer) не возвращает измененное состояние (кажется) - PullRequest
0 голосов
/ 20 февраля 2020

Я пытаюсь реализовать вариант «Ti c Ta c Toe» с React, который использует как Context, чтобы обеспечить общее состояние для всего приложения и его дочерних компонентов («Store»). ") и крюк редуктора (useReducer). По сути, пытаясь go «Путь Redux» без Redux, используя эти новые инструменты React.

Теперь у состояния есть два элемента, один из которых представляет собой двумерный массив строк (3 строки 3 строковых столбца) с именем squares, а другой - currentShape - который должен содержать либо "X", либо "O"

При щелчке по квадрату отправляется действие squareClick и (на данный момент) должен делать только эти две вещи:

  1. Устанавливает элемент в массиве sqaures, чтобы он стал state.currentShape (предоставляя row & col).
  2. Переключить state.currentShape на другую форму.

Вот так выглядит редуктор:

const SquareReducer = (state, action)=> {
    switch (action.type) {
        case 'squareClick':
            let squares = state.squares;
            squares[action.row][action.col] = state.currentShape;
            return {
                squares,
                currentShape: (state.currentShape === "X" ? "O" : "X")
            }

        default:
            return state;
    }
}

Это компонент Square:

const Square = ({row, col})=> {
    const { appState } = useContext(StateContext);
    const [state, dispatch] = useReducer(SquareReducer, appState);
    return (
        <div className="square"
            onClick={()=> {
                if (!state.squares[row][col]) {
                    dispatch({type:"squareClick", row, col});
                }

           }} >
            { appState.squares[row][col] }
        </div>
    )
}

Вот как компонент приложения написан и инициализирован:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            squares: [ ["", "", ""], 
                       ["", "", ""],
                       ["", "", ""] ],
            currentShape: "X"
        }

        this.squares = 
        <>
        <Square row="0" col="0" />
        <Square row="0" col="1" />
        <Square row="0" col="2" />
        <Square row="1" col="0" />
        <Square row="1" col="1" />
        <Square row="1" col="2" />
        <Square row="2" col="0" />
        <Square row="2" col="1" />
        <Square row="2" col="2" />
        </>
    }

    render() {
        return (
            <StateProvider value={{
                appState:    this.state,
                setAppState: this.setState}}>
                    { this.squares }
            </StateProvider>
        );
    }
}

Теперь: неважно, что, когда нажимается квадрат:
Массив squares равен обновлено, и если я укажу состояние из редуктора console.log - я всегда буду видеть самый обновленный, правильный squares массив Но свойство currentShape всегда сохраняет значение «X». Это так, , даже если я жестко закодирую «O» как значение (без условия).

Я не уверен, почему это происходит - с одной стороны, я могу видим, что редуктор предположительно получает обновленное состояние (массив sqaures представлен справа) - с другой стороны, кажется, всегда сохраняет начальное значение для currentShape.

Кто-нибудь есть идеи, почему?

...