Как я могу написать комбо редуктор / создатель действия, чтобы обновить состояние при нажатии кнопки? - PullRequest
0 голосов
/ 06 ноября 2019

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

Что работает:

  1. Карты отображаются правильно с правильными данными изсостояние, используя state.map () и mapStateToProps ()

  2. Действие LEVEL_UP отправляется по щелчку, как я вижу его в инструментах избыточного разработчика

Что не работает:

  1. На самом деле действие еще ничего не делает
  2. Все, что я пробовал, приводит к неопределенности, поэтому у меня возникают проблемы с доступом кнужные данные в редукторе
**TeambuilderCards.js** 

import React from "react";
import { connect } from "react-redux";

import TeamBuilderCard from "./TeamBuilderCard.js";

const TeamBuilderCards = ({ teamMembers }) => {
  return (
    <div className="ui centered cards">
      {teamMembers.map(teamMember => (
        <TeamBuilderCard
          key={teamMember.id}
          name={teamMember.name}
          xp={teamMember.xp}
        />
      ))}
    </div>
  );
};

const mapStateToProps = state => {
  return {
    teamMembers: state
  };
};

export default connect(mapStateToProps)(TeamBuilderCards);
**Teambuildercard.js**

import React from "react";
import { connect } from "react-redux";

import { levelUp, levelDown } from "../actions";

const roundUp = num => Math.ceil(num / 100) * 100;

const TeamBuilderCard = (props, dispatch) => (
  <div className="ui card">
    <div className="content">
      <div className="header">{props.name}</div>
      <div className="description">
        <h3>Current Level: {props.xp.toString().slice(0, 1)}</h3>
        <p>XP is currently {props.xp}</p>
        <p> {roundUp(props.xp) - props.xp} xp points to to next level</p>
      </div>
      <div className="meta">
        Increase or decrease {props.name}'s level with the buttons below
      </div>
    </div>
    <div className="extra content">
      <div className="ui two buttons">
        <div className="ui basic green button" onClick={props.levelUp}>
          Level up
        </div>
        <div className="ui basic pink button" onClick={props.levelDown}>
          Level down
        </div>
      </div>
    </div>
  </div>
);

const mapDispatchToProps = { levelUp, levelDown };

export default connect(
  null,
  mapDispatchToProps
)(TeamBuilderCard);

**actions.js**

export const LEVEL_UP = "LEVEL_UP";
export const LEVEL_DOWN = "LEVEL_DOWN";

export function levelUp() {
  return { type: LEVEL_UP };
}

export function levelDown() {
  return { type: LEVEL_DOWN };
}
**reducers/index.js**

import { LEVEL_UP, LEVEL_DOWN } from "../actions";
import preloadedState from "../preloadedState"; *//preloadedState is and array and I want to modify state[i].xp*

const initialState = preloadedState;

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case LEVEL_UP:
      return state; *//want to add 100 XP*
    case LEVEL_DOWN:
      return state; *//want to subtract 100 XP*
    default:
      return state;
  }
}
*preLoadedState.js* //Just the first 3 objects in the array

const preloadedState = [
  {
    id: "0",
    name: "Pete",
    xp: 153
  },
  {
    id: "1",
    name: "Jane",
    xp: 121
  },
  {
    id: "2",
    name: "Jim",
    xp: 188
  }

];

export default preloadedState;

Ответы [ 3 ]

0 голосов
/ 06 ноября 2019

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


export const reducer = (state = preloadedState, action) => {
  let newState = [...state] // now we can manipulate newState
  switch (action.type) {
    case 'LEVEL_UP':
        newState[action.index].xp = state[action.index].xp + 100
        return newState
    case 'LEVEL_DOWN':
       newState[action.index].xp = state[action.index].xp - 100
        return newState
    case 'ERROR':
        console.log('has been error, ', action.err)
        return state
    default:
        return state
  }
}

заметьте, я использую индекс в массиве вызываемыхпользователь должен добавить / уменьшить XP от нужного пользователя.


/create one action for example

export const levelUp = index => {
return (dispatch, getState) => {
    try {
        dispatch({
            type: 'LEVEL_UP',
            index
        })
    } catch (err) {
        dispatch({
            type: 'ERROR',
            err
        })

      }
  }
 }

и последнее, что нам нужно сделать, это отправить индекс / что бы вы не изменили в соответствии с внешним интерфейсом


   <div className="ui basic green button" onClick={()=>props.levelUp(index)}> //you should define the index here
      Level up
    </div>
0 голосов
/ 06 ноября 2019

На самом деле предыдущий ответ, который я принял, вернул в консоли некоторые ошибки, связанные с изменением состояния. Было также предупреждение о несериализуемых данных. Эта проблема была решена путем игнорирования проверки в configureStore () команды activ-starter-kit.

Однако теперь это работает, как и планировалось, без ошибок в консоли, но все равно большое спасибо, потому что все остальные предложения hagai harari сделалитрюк.

import preloadedState from "../preloadedState";

export const reducer = (state = preloadedState, action) => {
  switch (action.type) {
    case "LEVEL_UP":
      return state.map((xpUp, index) => {
        if (index === action.index) {
          return Object.assign({}, xpUp, {
            xp: state[action.index].xp + 100
          });
        }
        return xpUp;
      });
    case "LEVEL_DOWN":
      return state.map((xpDown, index) => {
        if (index === action.index) {
          return Object.assign({}, xpDown, {
            xp: state[action.index].xp - 100
          });
        }
        return xpDown;
      });
    case "ERROR":
      console.log("There has been an error, ", action.err);
      return state;
    default:
      return state;
  }
};
0 голосов
/ 06 ноября 2019

импорт и использование карты Ladash для просмотра массива объектов

Редукторы:

import map from 'lodash/map'

case LEVEL_UP:
      let nextstate = map(preloadedState,(eachobject,index)=>{
          let xp = eachobject.xp 
          eachobject.xp = xp + 100; 
      })
      return nextstate;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...