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的帖子标题。不应该有多个对象包含相同的信息。因此,基本上我只需要获取每个帖子的描述,在获取之前,是否检查帖子对象中已经存在的描述?