【问题标题】:ReactJS - Props not available immediately inside componentDidMount on a refreshReactJS - 刷新时在 componentDidMount 内无法立即使用道具
【发布时间】:2016-08-20 23:08:14
【问题描述】:

遇到一个令人沮丧的问题,希望有人能提供帮助。在https://github.com/georgecook92/Stir/blob/master/src/components/posts/viewPosts.jsx 获得完整的回购。

直接进入代码 -

componentDidMount() {
    const {user_id,token} = this.props.auth;
    this.props.startLoading();
    console.log('props auth', this.props.auth);
    if (user_id) {
      console.log('user_id didMount', user_id);
      this.props.getUserPosts(user_id, token);
    }

  }

如果组件是通过 ui 从另一个组件加载的,它会按预期运行。但是,如果页面被刷新,则 user_id 等不能立即用于 componentDidMount。

我已经检查过了,它稍后可用,但我发现如果我将 AJAX 调用移动到渲染方法或其他生命周期方法(如 componentWillReceiveProps) - 道具会不断更新并锁定 UI -不理想。

如果我将 ajax 调用移至 render 方法,我也不确定为什么每秒会进行多个 ajax 调用。

希望你能帮上忙!谢谢。

编辑。

    export function getUserPosts(user_id, token){
  return function(dispatch) {

    if (window.indexedDB) {
      var db = new Dexie('Stir');
      db.version(1).stores({
        posts: '_id, title, user_id, text, offline',
        users: 'user_id, email, firstName, lastName, token'
      });

      // Open the database
      db.open().catch(function(error) {
        alert('Uh oh : ' + error);
      });

      db.posts.toArray().then( (posts) =>  {
        console.log('posts:', posts);
        if (posts.length > 0) {
          dispatch( {type: GET_POSTS, payload: posts} );
        }
      });
    }

    axios.get(`${ROOT_URL}/getPosts?user_id=${user_id}`, {
      headers: {
        authorisation: localStorage.getItem('token')
      }
    }).then( (response) => {
      console.log('response from getPosts action ', response);

      dispatch( {type: GET_POSTS, payload: response.data} );
      dispatch(endLoading());

      response.data.forEach( (post) => {

        if (post.offline) {

          if (window.indexedDB) {
            db.posts.get(post._id).then( (result) => {
              if (result) {
                //console.log('Post is already in db', post.title);
              } else {
                //console.log('Post not in db', post.title);
                //useful if a posts offline status has changed
                db.posts.add({
                  _id: post._id,
                  title: post.title,
                  user_id: post.user_id,
                  text: post.text,
                  offline: post.offline
                });
              }
            } )
          }
        }
      } );

    })
      .catch( (err) => {
        console.log('error from get posts action', err);
        if (err.response.status === 503) {

          dispatch(endLoading());
          dispatch(authError('No internet connection, but you can view your offline posts! '));
        } else {
          dispatch(endLoading());
          dispatch(authError(err.response.data.error));
        }

      });
  }

}

【问题讨论】:

  • 在运行时粘贴 ajax 代码?
  • 您是否尝试过使用shouldComponentUpdate 来避免重绘?你可以阅读更多关于它的信息here。或者,可以更改您的应用程序逻辑,仅在 AJAX 响应(以及 user_id 的值)准备好时绘制组件。
  • 如果您将 AJAX 调用移动到渲染,假设它正在调用一个 redux 操作,它会将有效负载分派到存储并触发将再次调用渲染的新更新。因此,您有一个无限循环。 在渲染中使用附带效果总是一个坏主意。

标签: javascript ajax reactjs redux


【解决方案1】:

我建议使用componentWillReceiveProps 并将您的道具保存为状态以在发生更改时触发重新渲染(例如,道具从未定义更改为具有值)。这样的事情会起作用:

import React, {Component} from 'react';

// using lodash for checking equality of objects
import _isEqual from 'lodash/isEqual';

class MyComponent extends Component {
    constructor(props={}) {
        super();
        this.state = props;
    }

    // when the component receives new props, like from an ajax request,
    // check to see if its different from what we have. If it is then 
    // set state and re-render
    componentWillReceiveProps(nextProps) {
        if(!_isEqual(nextProps, this.state)){
            this.setState(nextProps);
        }
    }
    render() {
        return (
            <div>{this.state.ItemPassedAsProp}</div>
        );
    }
}

【讨论】:

    猜你喜欢
    • 2016-07-21
    • 2020-02-04
    • 2020-05-09
    • 2018-11-26
    • 2019-08-24
    • 2017-06-28
    • 2018-07-25
    • 2015-12-28
    • 1970-01-01
    相关资源
    最近更新 更多