保持组件的渲染,直到商店完成水合作用

时间:2017-05-24 13:49:44

标签: reactjs react-redux

我正在提取我的初始数据:

export function populate (dispatch) {
  let posts = []
  dispatch(requestNews())
  fetch(someEndPoint)
  .then(payload => payload.json())
  .then(items => {
    //some fetching logic that populates posts list above
  })
  .then(() => { dispatch(receiveNews(posts)) })
  .catch(err => {
    console.log(err)
  })
}

function request () {
  return {
    type: REQUEST_NEWS,
    payload: {
      populating: true
    }
  }
}

function receive (posts) {
  return {
    type: RECEIVE_NEWS,
    payload: {
      populating: false,
      posts
    }
  }
}

正如您在上面所看到的,我正在使用一个名为populating的字段设置商店,该字段以false开头,并在调度'request'时更改为true,然后在调度'received'时返回false。

然后我的组件如下所示:

import { populateNews } from '../modules/news'

class News extends React.Component {
  constructor (props) {
    super(props)
    //this.mapPosts = this.mapPosts.bind(this)
  }

  componentWillMount () {
    populateNews(this.props.dispatch)
  }

  render () {
    if (!this.props.news.populating) {
      return (
        <div>
          {this.props.news.posts[0].title}
        </div>
      )
    } else {
      return (
        <div>loading</div>
      )
    }
  }
}

在初始加载渲染之前,即使我的填充开关按预期来回变化,也会在使用提取的帖子填充商店之前调用渲染。

我尝试使用组件上的本地状态来处理它,所以它的构造函数有:this.state = {populating: false}然后动作创建者改变了它,但得到了相同的结果。

所以目前我的解决方案是检查状态是否有一个名为“posts”的片段,该片段是在获取内容后创建的,以及是否有渲染它。像这样:

 render () {
    return (
      <div>
        {this.props.news.posts ? <div>{this.props.news.posts[0].title}</div> : null }
      </div>
    )
  }

这当然只是渲染组件,然后在使用帖子更新商店后再次呈现它,并且不是最佳解决方案,例如等待渲染,直到完成提取并填充存储。

这里有一个很长的讨论: https://github.com/reactjs/react-redux/issues/210

如何延迟或更好地放置渲染本身的条件?

1 个答案:

答案 0 :(得分:0)

嗯,您可能想要更改if语句。除非您的商店正在将populating初始化为true,否则初始加载时它将为undefined,并将通过您的if (!this.props.news.populating)验证,该验证将尝试呈现帖子标题。改变你的条件,寻找一个真实的价值,而不是一个虚假的价值,你应该有更多的控制权。