当我的父母呈现它覆盖子消息时,我为每个父组件获得了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>
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;
}
}
答案 0 :(得分: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"];
答案 1 :(得分:0)
设计中存在一些问题。
在父组件中,您编写了
<MessageList projectId={item.id} />
projects
状态发生变化,就会呈现。
MessageList
组件本身中,您使用的是州messages: state.messages
当state.messages
发生变化时,会再次要求组件重新渲染。
因此,通过这种方式,您的消息组件将呈现两次。
解决方案:
在父组件中,删除要传递的属性。
而不是<MessageList projectId={item.id} />
写<MessageList />
从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)将使用更新的项目标识数据重新呈现。