Реакция обновления локальных состояний при обновлении редуктора - PullRequest
0 голосов
/ 17 ноября 2018

Я делаю проект, используя React и Redux.Я обновляю редуктор массивом, а затем отображаю этот массив в компонент.Компонент имеет состояние, которое используется для условного рендеринга изображения.Я хочу, чтобы это состояние компонентов сбрасывалось до значения по умолчанию при каждом обновлении состояния редукторов.

Вот редуктор:

const reducer = (state={board : []}, action) => {
    switch (action.type) {
      case 'MAKE_BOARD':
      return Object.assign({}, state, {
        board: action.payload
      })
      default:
        return state  
    }
}

Вот страница App.js, которая вызывает редуктор:

import React, { Component } from 'react';
import './App.css';
import Board from '../Board/Board'
import {connect} from 'react-redux'


const mapReduxStateToProps= (reduxState) => ({
  reduxState
})

class App extends Component {
  state = {
    size : '8',
    squareArray : []
  }

  handleChange =(event) => {
    this.setState({
      ...this.state,
      size : Number(event.target.value)
    })
    console.log(this.state)
  }

  //This function makes a an array of numbers with 1/4 'X's and 3/4 'O's
  boardMaker = (number) => {
    this.setState({squareArray:[]});
    let size = number*number;
    let placeHolderArray = []

    for(let i=0; i<size; i++){
      placeHolderArray.push('O')
    }
    for(let j=0; j<size/4;j++){
      placeHolderArray[Math.floor(Math.random()*size)] = 'X'
    }

    this.setState({squareArray: placeHolderArray})
    console.log(placeHolderArray)
    console.log(this.state.squareArray);
    this.props.dispatch({type:'MAKE_BOARD', payload: placeHolderArray})
    this.props.dispatch({type: 'SET_SIZE', payload : this.state.size})
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <input onChange={this.handleChange} placeholder='Size'/>
          <button onClick={()=>this.boardMaker(this.state.size)}>Make Board</button>

          <div className='board' style={{width: 40*this.props.reduxState.size.size}}>

            {/* {this.state.squareArray.map(space => {
              return(
                <div className='square'>{space}</div>
              )
            })} */}
            {JSON.stringify(this.props.reduxState)}
            {this.props.reduxState.reducer.board.map((space,index) => 
              <Board keys={index} id={space}/>
            )
            }
          </div>

        </header>
      </div>
    );
  }
}

export default connect(mapReduxStateToProps)(App);

Вот board.js, где редукторотображается:

import React, { Component } from 'react';
import './Board.css'
import { connect } from 'react-redux';


const mapReduxStateToProps = (reduxState) => ({reduxState})

class Board extends Component {
  state = {
    clicked: false,
    displayFlag: false,
    counter: 0,
  }


  imageDisplay= () => {
    if(!this.state.clicked && !this.state.displayFlag){
      return <img key={this.props.id} src='images/Frog-1.png' alt='Not Clicked'/>
    } else if(this.state.displayFlag){
      return <img src='images/Yellow.png' alt='None' />
    } else {
      return this.state.counter;
    }
  }

  handleMouseDown =  e => {
    document.oncontextmenu = function() {
      return false;
  }
    e = e || window.event;
    //console.log(e.which)
    console.log(this.state)
    switch(e.which) {
      case 1 : this.showNumber(); break;
      case 2 : break;
      case 3 : this.displayFlag(); return false;
      default: break;  
    }
  }

  displayFlag= () => {
    console.log('running')
    this.setState({...this.state, displayFlag : !this.state.displayFlag })
    return this.state.displayFlag;
  }

  showNumber= () => {
    console.log('run')
    let Xcounter = 0;
    let edge = Math.sqrt(this.props.reduxState.reducer.board.length)
    console.log(edge)
    let keys = this.props.keys
    let board = this.props.reduxState.reducer.board
    let minX = keys%edge === 0 ? 0 : -1;
    let maxX = keys%edge === (edge-1) ? 0 : 1;
    let minY = Math.floor(keys/edge) == 0 ? 0 : -1;
    let maxY = Math.floor(keys/edge) == (edge-1) ? 0 : 1;
    for(let x = minX; x <= maxX; x++){
      for(let y = minY; y<=maxY; y++){
        if(board[keys+x+(y*edge)]=== 'X'){
          Xcounter++

        }
      }
    }
    if(this.props.id === 'X'){
      this.setState({...this.state, clicked: true, counter: 'X'})
      return this.state.counter;
    }
    this.setState({...this.state, clicked: true, counter: Xcounter})
    return this.state.counter;
  }



  render() {
    return (
      <div className="App">
          <div onMouseDown={()=>this.handleMouseDown()} className='square'>{this.imageDisplay()}</div>

      </div>
    );
  }
}

export default connect(mapReduxStateToProps)(Board);

Я хочу, чтобы локальное состояние на плате сбрасывалось при обновлении редуктора.Я, вероятно, могу сделать это, добавив свойства в редуктор и используя их в компоненте, но я надеюсь, что есть лучший метод.

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Рассматривая ваш вариант использования - вам нужно очищать локальное состояние при каждом MAKE_BOARD действии.

Вот два подхода, которые я имел в виду -

  1. Вы можетепроверьте реквизиты, которые обновляются, и поместите условие в ваши (в зависимости от вашей версии реакции) методы жизненного цикла, такие как componentWillReceiveProps / getDerivedStateFromProps / componentDidUpdate, и очистите локальное состояние.
  2. Вы можетесоздайте отдельное действие в строках RESET_ACTION_NAME, которое будет возвращать ваше начальное состояние (пустое) при каждом обновлении.Но для того, чтобы он функционировал правильно, вам нужно поместить ваше локальное состояние в качестве объекта в хранилище редуксов.

PS: Если вы знаете, что ваше действие по сбросу состояния имеет только ограниченную область действияВам не нужно указывать свое состояние в магазине.Но если вы знаете, что это действие распространяется на несколько компонентов, вы можете рассмотреть возможность преобразования локального состояния в объект хранилища с избыточностью.

0 голосов
/ 17 ноября 2018

Это немного влияет на мнение проектировщиков, но я думаю, что самый простой способ справиться с этим - перевести состояние платы также в состояние редукции, а не в локальное состояние (возможно, в отдельном редукторе в том же магазине), потому что (если я правильно понимаю) вы действительно говорите, что хотите, чтобы его состояние изменялось (сбрасывалось) в зависимости от действия «MAKE_BOARD».

Другой альтернативой может быть включение целочисленного идентификатора доски в ваше состояние приращения, которое вы увеличиваете каждый раз, когда переделываете доску. Тогда, если вы используете это как «ключевое» свойство вашей доски, я считаю, что это приведет к ее автоматическому сбросу, поскольку она размонтирует предыдущую плату и создаст новую.

Если вы хотите получить больше подробностей о том, как это сделать, я рекомендую поместить версию кода в codepen или codeandbox и поделиться ею в своем вопросе (но хорошо, что вы включаете большую часть соответствующего кода). непосредственно в тексте вашего вопроса).

...