【问题标题】:why this Component only works on start but not when pressing button为什么此组件仅在启动时有效,但在按下按钮时无效
【发布时间】:2019-11-15 19:53:40
【问题描述】:

我学习了 React-Redux,需要帮助理解为什么这个组件只在启动时起作用,而在我按下按钮时不起作用。 调试时在图片中断执行中启动断点,但是当我按下按钮时,图片中显示了此错误。

当断点命中时,我对{toasts.map(toast => { 大喊大叫,并且数组大小为零。但是当我按下按钮时,断点甚至没有命中

有什么办法吗?

更新

我有这个 configureStore.js

import { combineReducers } from "redux";
import { createStore, applyMiddleware, compose } from "redux";
import { forbiddenWordsMiddleware } from "../middleware";
import  ToastsReducer from '../reducers/ToastsReducer';
import  RootReducer from '../reducers/RootReducer';

const storeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const reducers = {
     toastsReducer: ToastsReducer,
     rootReducer: RootReducer
  };

  const reduce = combineReducers({
    ...reducers,
  });

const store = createStore(
    reduce,
    storeEnhancers(applyMiddleware(forbiddenWordsMiddleware))
);
export default store;

RootReducer.js

import { ADD_ARTICLE } from "../constants/action-types";
import { FOUND_BAD_WORD } from "../constants/action-types";

const initialState = {
  articles: []
};
export default function reducer(state = initialState, action) {
  if (action.type === ADD_ARTICLE) {
    return Object.assign({}, state, {
      articles: state.articles.concat(action.payload)
    });
  }

  if (action.type === FOUND_BAD_WORD) {
    //return Object.assign({}, state, {
    //  articles: state.articles.concat(action.payload)
    // });
  }
  return state;
}

ToastsReducer.js

import { ADD_TOAST, REMOVE_TOAST } from "../constants/action-types";

const initialState = {
  toastList: []
};

export default function toasts(state = initialState, action) {
  const { payload, type } = action;

  switch (type) {
    case ADD_TOAST:
      return [payload, state.toastList];

    case REMOVE_TOAST:
      return state.toastList.filter(toast => toast.id !== payload);

    default:
      return state;
  }
}

更新

当我按两次按钮时显示 RootReducer.jsx 和 Toasts.jsx 的图片,

Toast.js

import PropTypes from "prop-types";
import React, { Component } from "react";

class Toast extends Component {
  render() {
    return (
      <li className="toast" style={{ backgroundColor: this.props.color }}>
        <p className="toast__content">
          {this.props.text}
        </p>
        <button className="toast__dismiss" onClick={this.props.onDismissClick}>
          x
        </button>
      </li>
    );
  }

  shouldComponentUpdate() {
    return false;
  }
}

Toast.propTypes = {
  color: PropTypes.string.isRequired,
  onDismissClick: PropTypes.func.isRequired,
  text: PropTypes.string.isRequired
};

export default Toast;

【问题讨论】:

    标签: react-redux react-component


    【解决方案1】:

    请分享您的减速器代码。很可能,您没有在 reducer 中为 toastList 设置初始状态,或者 toastsReducer.toastList 出现错误。

    尝试以下方法:

    • 将第 34 行更改为 toasts: state.toastsReducer
    • 注释从 10 到 19 的行并插入以下内容以确保 toasts 是一个数组。
    console.log(toasts);
    console.log(toasts.toastList);
    return null;
    

    如果两者都未定义,则reducer返回的值不对。

    在 ToastsReducer.js 中:

    更改以下内容:

     case ADD_TOAST:
          return [ ...state.toastList, payload]; //<--- Here
    

    当您执行 return[payload,state.toastList] 时,它会将另一个数组附加到 toastList。

    运行以下查看:

    toastList = ['abc'];
    
    // Right way to add an item to an array.
    toastList = [...toastList, 'def'];
    
    console.log(toastList);
    console.log('-----');
    // Adds an array to the array. Incorrect way.
    toastList = [toastList, 'ghi'];
    
    console.log(toastList);

    ---更新---

    将您的 ADD_TOAST 案例更改为:

    return { toastList: [...state.toastList, payload] };
    

    你应该很高兴。

    【讨论】:

    • 我添加了减速器代码。谢谢,当我按三次按钮时,我按照您所说的做了并进入调试日志:- ....Array(2) [Object, undefined] Toasts.jsx:10 undefined Toasts.jsx:11 ....Array(2 ) [对象,未定义] Toasts.jsx:10 未定义 Toasts.jsx:11 ....Array(2) [对象,未定义] Toasts.jsx:10 未定义
    • 即使在将 ADD_TOAST 案例更改为我建议的情况之后?
    • 当我更改 ADD_TOAST 并按下按钮时,我进入日志 Array(1) [Object] Toasts.jsx:10 undefined,当我再次按下按钮时,我得到 - TypeError: state.toastList is not iterable
    • 你能用 ToastsReducer.js 和 Toasts.jsx 的新变化更新问题吗?
    • 我在github 有这个项目,希望你能看到问题所在
    【解决方案2】:

    只需检查您的 toasts 数组是否包含数据,

    {toasts && toasts.length > 0 ? toasts.map(toast => {...}) : null}
    

    【讨论】:

    • 感谢我收到Cannot read property 'length' of undefined。所以地图不是空的而是别的东西
    • Cannot read property 'length' of undefined 这个错误也意味着你的toasts 数组没有被传递给这个组件。在调用此组件之前确保它具有值。
    猜你喜欢
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多