Reactjs 清除重复状态
我有一个组件Reactjs 清除重复状态,reactjs,redux,react-redux,Reactjs,Redux,React Redux,我有一个组件postshow,显示所选的帖子: @connect((state) => ({post: state.posts.post}), {fetchPost}) class PostsShow extends Component { componentDidMount() { this.props.fetchPost(this.props.match.params.id); } render() { const { post } = this.
postshow
,显示所选的帖子:
@connect((state) => ({post: state.posts.post}), {fetchPost})
class PostsShow extends Component {
componentDidMount() {
this.props.fetchPost(this.props.match.params.id);
}
render() {
const { post } = this.props;
if (!post) {
return <div></div>;
}
return (
<div>
<Link to='/'>Back</Link>
<h3>{post.title}</h3>
<h6>Categories: {post.categories}</h6>
<p>{post.content}</p>
</div>
);
}
}
减速器:
export function clearPost() {
return {
type: CLEAR_POST,
payload: null
}
}
const INITIAL_STATE = { all: [], post: null };
export default function (state = INITIAL_STATE, action) {
switch (action.type) {
// ... Other cases
case CLEAR_POST:
return { ...state, post: null }
default:
return state;
}
}
class PostsShow extends Component {
componentDidMount() {
this.props.fetchPost(this.props.match.params.id);
}
componentWillUnmount() {
this.props.clearPost();
}
render() {
// Old render
}
}
组件:
export function clearPost() {
return {
type: CLEAR_POST,
payload: null
}
}
const INITIAL_STATE = { all: [], post: null };
export default function (state = INITIAL_STATE, action) {
switch (action.type) {
// ... Other cases
case CLEAR_POST:
return { ...state, post: null }
default:
return state;
}
}
class PostsShow extends Component {
componentDidMount() {
this.props.fetchPost(this.props.match.params.id);
}
componentWillUnmount() {
this.props.clearPost();
}
render() {
// Old render
}
}
这是react with redux的好方法吗?您的状态结构不理想。试着像这样保持你的帖子:
posts: {
byID: {
1: {/*the post* no 1/},
2: {/*the post* no 2/},
// ...
}
allIDs: [2, 1 /*, ...*/],
}
通过这种方式,您可以为列表视图提供帖子id的有序列表,并通过以下状态获取单个帖子:This.posts.byID['thePostID']
也请阅读上的redux文档
这也将解决您的问题,因为当您从存储中获取的帖子的id不存在时,它将是
未定义的
,因此呈现为空的div
。加载指示器将是最好的显示方式。这是因为您正在进行异步调用,这需要时间来获取新的日期,这就是为什么当fetch posts获取新数据时,您的组件将更新并呈现它。
您可以有两种方法:
1) 您可以创建一个异步函数,该函数将调度一个操作,该操作将使用有效负载更新减速器
status :LOADING,
fetch函数返回新数据后,再次调度一个
将根据需要更新减速器
status:SUCCESS
在您的组件中,检查商店在道具中收到的状态是否为“加载”或“成功”,如果成功,则显示新状态,如果加载,则继续显示一些文本,如组件正在加载:
这是一个例子
SomeComponent.js
export default class SomeComponent extends Component {
constructor (props) {
super(props)
this.model = {}
}
render () {
const {
status
} = this.props
const loading = status === 'LOADING'
return (
<Layout>
<Row>
<FormField
label='First Name'
id='first-name'
value={details.firstName}
onChange={this.update('firstName’)}
disabled={loading}
mandatory
/>
</Row>
</Layout>
)
}
}
Reducer.js
export default function reducer (state = {}, action = {}) {
switch (action.type) {
case constants.DATA_FETCHING:
return Object.assign({}, state, {
data: {},
status: 'LOADING'
})
case constants.DATA_FETCHED:
return Object.assign({}, state, {
data: action.data,
status: 'SUCCESS'
})
default:
return state
}
}
第二种方法
您所做的,但为了清楚起见,请尝试使用第一个。不应该是
状态。posts
将post id映射到实际post的数组或对象?您的问题是,state.posts.post在上次提取后仍然存在。@trixn,是的,但我不明白为什么会有问题?在我看来,这似乎是实现此类目标的常用方法……或者我误解了你的问题?state.posts.post
对我来说毫无意义。为什么名为posts
的对象具有名为post
的属性。它应该是一个post数组或post id到post对象的映射。这样,如果您连接组件以按post id从state获取新post,则具有另一个id的新post将呈现为空div。@trixn state.posts是一个具有2个props的对象。-<代码>全部:[],post:null
。道具all
代表一个包含所有帖子的数组,post
代表当前获取的包含所有细节的帖子(通常,如果你想获取描述和所有细节,你需要用帖子的id
发出另一个请求)。我会触发另一个动作创建者,比如:{type:'fetching_start'}
并将显示加载程序,而不是post
数据。当数据准备好后,我会触发另一个动作creator{type:'fetching_end'}
来隐藏加载程序并显示数据。这是一种常见的模式,你让我感到恶心。你不可能只通过一个请求就获得关于post的所有信息。所有帖子的列表只包含标题
和id
。为了获得描述(这是查看帖子所必需的),您需要提出另一个请求。因此,该请求的结果存储在名为post
的post
对象的单独属性中。为什么会出现问题?您的posts
端点应至少使用post id和其他信息(如标题)进行应答。但是您必须将post数据存储在post对象中。您可以在以后轻松地获取该帖子的其他(缺失)信息,并将其存储在同一个帖子对象中。我看这没什么问题。规范化您的状态很重要,否则您将遇到多个您已经遇到的问题。好的,为什么不显示您已经拥有的信息(标题),然后只获取缺少的数据?您应该真正阅读我在回答中链接的redux docs部分,“因此,该请求的结果存储在posts对象的单独属性post中”。这是你的问题。它不应存储在另一个对象中。这违反了“单一真相来源”原则。它应该在同一个对象中,该对象已经具有具有此id的帖子标题。不应该有多个对象包含相同的信息。因此,基本上我只需要获取每个帖子的描述,在获取之前,是否检查帖子对象中已经存在的描述?