【问题标题】:react child component is overwriting redux state反应子组件正在覆盖 redux 状态
【发布时间】:2017-08-23 17:16:13
【问题描述】:

当我的父级呈现时,它会覆盖子消息,我为每个父组件收到 2 条相同的消息。请帮我。以下是我的父组件。 例如,我的父母有 4 个项目。

{
project1: { message1: 'hello this message for project 1',message2: 'messsage 2 for project 1'},    
project2: { message1: 'hello this message for project 2',message2: 'messsage 2 for project 2'}
};

但在输出中我得到了

project1: { message1: 'hello this message for project 2',message2: 'messsage 2 for project 2'};
project2: { message1: 'hello this message for project 2',message2: 'messsage 2 for project 2'};

我希望项目 1 显示自己的消息,项目 2 显示自己的消息,但 redux 正在覆盖我的状态。

  import React, { Component } from 'react';
  import PropTypes from 'prop-types';
  import { connect } from 'react-redux';
  import { projectsFetchData } from '../actions/projects';
  import MessageList from './MessageList';

  class Projects extends Component {
      componentDidMount() {
        this.props.fetchData('https://api.proworkflow.net/projects?apikey=9ZVM-873H-3JPK-C55Q-PWFE7MN-TR86485');
      }
      render() {
          if (this.props.hasErrored) {
              return <p>Sorry! There was an error loading the items</p>;
          }
          if (this.props.isLoading) {
              return <p>Loading…</p>;
          }
          return (
            <div className="container">
              <div className="panel panel-primary">
                <div className="panel-heading clearfix">
                  <div className="header-logo pull-left" />
                  <div className="pull-right heading">
                    <span className="glyphicon glyphicon-envelope" aria-hidden="true"></span>
                    &nbsp;Project Messages
                  </div>
                 </div>
                <div className="panel-body secondry">
                  {this.props.projects.map((item) => (
                    <div className="media" key={item.id}>
                      <div className="media-body">
                        <h4 className="media-heading"><i>{item.companyname}</i></h4>
                        <p><i>{item.title}</i></p>
                        <MessageList projectId={item.id} />
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          );
      }
  }
  Projects.propTypes = {
      fetchData: PropTypes.func.isRequired,
      projects: PropTypes.array.isRequired,
      hasErrored: PropTypes.bool.isRequired,
      isLoading: PropTypes.bool.isRequired
  };

  const mapStateToProps = (state) => {
      return {
          projects: state.projects,
          hasErrored: state.projectsHasErrored,
          isLoading: state.projectsIsLoading
      };
  };

  const mapDispatchToProps = (dispatch) => {
      return {
          fetchData: (url) => dispatch(projectsFetchData(url))
      };
  };

  export default connect(mapStateToProps, mapDispatchToProps)(Projects);

以下是我的子组件

  import React, { Component } from 'react';
  import PropTypes from 'prop-types';
  import { connect } from 'react-redux';
  import { messagesFetchData } from '../actions/messages';

  class MessageList extends Component {
      componentDidMount() {
        const projectId = this.props.projectId;
        this.props.fetchData(`https://api.proworkflow.net/projects/${projectId}/messages?apikey=9ZVM-873H-3JPK-C55Q-PWFE7MN-TR86485`);
      }
      render() {
          if (this.props.hasErrored) {
              return <p>Sorry! There was an error loading the items</p>;
          }
          if (this.props.isLoading) {
              return <p>Loading…</p>;
          }
          return (
            <div className="media-container">
              {this.props.messages.map((item) => (
              <div className="media" key={item.id}>
                <div className="media-left">
                  <a role="button">
                    <img className="media-object img-circle" src="http://www.gravatar.com/avatar/8c2f99e721ce7c2e8968ae2eec40c4dc?s=80&d=mm" alt="..."/>
                  </a>
                </div>
                <div className="media-body">
                  <h4 className="media-heading">{item.authorname}</h4>
                  <p dangerouslySetInnerHTML={{__html: item.content}}/>
                </div>
              </div>
              ))}
            </div>
          );
      }
  }
  MessageList.propTypes = {
      fetchData: PropTypes.func.isRequired,
      hasErrored: PropTypes.bool.isRequired,
      isLoading: PropTypes.bool.isRequired
  };

  const mapStateToProps = (state) => {
      return {
          messages: state.messages,
          hasErrored: state.messagesHasErrored,
          isLoading: state.messagesIsLoading
      };
  };

  const mapDispatchToProps = (dispatch) => {
      return {
          fetchData: (url) => dispatch(messagesFetchData(url))
      };
  };

  export default connect(mapStateToProps, mapDispatchToProps)(MessageList);

以下是我的孩子减速机

    export function messagesHasErrored(state = false, action) {
        switch (action.type) {
            case 'MESSAGES_HAS_ERRORED':
                return action.hasErrored;
            default:
                return state;
        }
    }
    export function messagesIsLoading(state = false, action) {
        switch (action.type) {
            case 'MESSAGES_IS_LOADING':
                return action.isLoading;
            default:
                return state;
        }
    }
    export function messages(state = [], action) {
        switch (action.type) {
            case 'MESSAGES_FETCH_DATA_SUCCESS':
              return action.messages;
            default:
              return state;
        }
    }

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

    这是因为两个项目共享相同的 redux-state。

    我不确定添加命名空间是否会对您有所帮助,因为您的项目列表可能包含任意数量的项目。但是,我认为它可能会给您一些解决共享状态问题的提示。

    having multiple instance of same reusable redux react components on the same page/route


    您可以添加一个 projectMessages Reducer,而不是使用消息 Reducer。

    在子减速器中

    export function projectMessages(state = {}, action) {
        switch (action.type) {
            case 'PROJECT_MESSAGES_FETCH_DATA_SUCCESS':
              return Object.Assign({}, state, {action.payload.projectId: action.payload.messages});
            default:
              return state;
        }
    }
    

    在行动中:

    export function projectMessagesFetchDataSuccess(messages, projectId) {
        return {
            type: "PROJECT_MESSAGES_FETCH_DATA_SUCCESS",
            payload: { projectId: projectId, messages: message }
        };
    }
    

    在MessageComponent中:通过

    获取项目的消息
    this.prop.projectMessages[this.props.projectId]
    

    例如:

    projectMessages = {"project1": ["m1", "m2", "m3"], "project2": ["m4", "m5", "m6"]};
    

    如果你想得到project2的消息,你可以这样做

    var messagesOfProject2 = projectMessages["project2"];
    

    【讨论】:

    • 但是我怎样才能得到特定项目的消息。?请帮帮我
    【解决方案2】:

    设计中存在一些问题。

    1. 在父组件中,你写了

      &lt;MessageList projectId={item.id} /&gt;

    每当projects 状态发生变化时都会渲染。

    1. MessageList 组件本身中,您正在使用状态messages: state.messages

    只要state.messages 发生变化,它就会要求组件重新渲染。

    这样,你的消息组件会被渲染两次。

    解决方案:

    在父组件中,删除您正在传递的属性。

    而不是&lt;MessageList projectId={item.id} /&gt;&lt;MessageList /&gt;

    projects: state.projects 声明中,projects 是状态的一部分。

    所以,在子组件中循环它(MessageList)。

    在子组件中,您的mapStatesToProps 将是

    const mapStateToProps = (state) => {
          return {
              messages: state.messages,// remove it
              hasErrored: state.messagesHasErrored,
              isLoading: state.messagesIsLoading,
              projects : state.projects //added in child component
          };
      };
    

    从状态树中删除 messages: state.messages 作为 MessageList 组件的唯一内部状态。您可以将其存储在内部并循环它

    在子组件中,在

    componentDidMount() {
        let projectId = null;
        this.props.projects.map((item) =>{
            projectId = item.id;
                this.props.fetchData(`https://api.proworkflow.net/projects/${projectId}/messages?apikey=9ZVM-873H-3JPK-C55Q-PWFE7MN-TR86485`);
    
        }) 
      }
    

    现在,每当父组件中的projects 状态发生变化时, 您的子组件 (MessageList) 将使用更新的项目 ID 数据重新呈现。

    【讨论】:

    • 但是我怎样才能得到特定项目的消息。?请帮帮我
    猜你喜欢
    • 2019-11-29
    • 2018-04-30
    • 2019-07-19
    • 2018-10-05
    • 1970-01-01
    • 2022-11-14
    • 2020-04-11
    • 2018-09-29
    • 2017-04-19
    相关资源
    最近更新 更多