【问题标题】:React: initial render fires before state is set (via ajax)React:在设置状态之前触发初始渲染(通过 ajax)
【发布时间】:2016-02-05 22:06:43
【问题描述】:

我已经进行了设置,以便 HomePage 组件为当前登录的用户呈现 UserShow。例如,如果一个 ID 为 2 的用户登录并访问 HomePage 页面,它将呈现他们的 UserShow

“正常”UserShow 工作正常。例如,如果您输入 /users/18,它将正确呈现。但是,当 HomePage 呈现它时它不起作用。

我是 React 的新手(尤其是它的生命周期方法),所以我的调试是在各个步骤中抛出警报。我想说最重要的发现是:

  1. currentUserID( ) 正在运行并返回正确的 ID
  2. componentDidMount 中硬编码 state.userID 的值会使事情正常工作

这两点让我相信 Render 在更新 state.userID 及其(正确的)返回值之前被调用了。更具体的是,它在 this.currentUserID() ajax 调用返回的 .success 部分之前呈现。如果是这样,在这样的 ajax 调用完成之前不进行初始渲染的最佳方法是什么?

我的代码处于意大利面条状态 - 这是我第一次使用 JavaScript 进行前端路由。我还通过使用用户的电子邮件作为 localStorage 中的令牌来管理会话——我也是 JS 中的会话的新手。请多多包涵。

主页组件:

var HomePage = React.createClass({

getInitialState: function(){
    return{
        didFetchData: false,
        userID: null,
    }
},

componentWillMount: function(){
    newState = this.currentUserID()
    this.setState({userID: newState}) 
    // this.setState({userID: 2})   //hard-coding the value works
},

currentUserID: function(){
    if(App.checkLoggedIn()){
        var email = this.currentUserEmail()
        this.fetchUserID(email)
    }else{
        alert('theres not a logged in user')
    }
},

currentUserEmail: function(){
    return localStorage.getItem('email')
},

fetchUserID: function(email){ //queries a Rails DB using the user's email to return their ID
    $.ajax({
        type: "GET",
        url: "/users/email",
        data: {email: email},
        dataType: 'json',
        success: function(data){
            this.setState({didFetchData: 'true', userID: data.user_id})
        }.bind(this),
        error: function(data){
            alert('error! couldnt fetch user id')
        }
    })
},

render: function(){
    userID = this.state.userID
    return(
        <div>
            <UserShow params={{id: userID}} />
        </div>
    )
}
})

UserShow 组件:

var UserShow = React.createClass({

getInitialState: function(){
    return{
        didFetchData: false,
        userName: [],
        userItems: [],
        headerImage: "../users.png"
    }
},

componentDidMount: function(){
    this.fetchData()
},

fetchData: function(){  
    var params = this.props.params.id
    $.ajax({
        type: "GET",
        url: "/users/" + params,
        data: "data",
        dataType: 'json',
        success: function(data){
            this.setState({didFetchData: 'true', userName: data.user_name, userItems: data.items, headerImage: data.photo_url})
        }.bind(this),
        error: function(data){
            alert('error! couldnt load user into user show')
        }
    })
},

render: function(){
    var userItem = this.state.userItems.map(function(item){
        return <UserItemCard name={item.name} key={item.id} id={item.id} description={item.description} photo_url={item.photo_url} />
    })
    return(
        <div>
            <Header img_src={this.state.headerImage} />

            <section className="body-wrapper">
                {userItem}              
            </section>
        </div>
    )
}
})

【问题讨论】:

  • fetchUserID()fetchData() 是异步的,但您正在尝试同步使用它们。他们需要在 ajax 调用完成时通知回调,并且您的其余代码必须在该回调中继续。

标签: javascript jquery ruby-on-rails ajax reactjs


【解决方案1】:

所以你要做的是避免渲染任何东西,直到你的 ajax 请求返回你的结果。

如果状态是您想要的状态,您可以在渲染方法中进行检查。如果不是,则返回 null、加载程序或其他一些标记。当componentDidMount再设置状态时,会触发重新渲染,因为此时设置了userID,所以会返回userShow组件

例子:

render(){
  if(this.state.userID === null){
     return null; //Or some other replacement component or markup
  }

  return (
    <div>
        <UserShow params={{id: userID}} />
    </div>
  );

}

在 userShow 组件中获取数据可以这样完成:

componentWillReceiveProps(nextProps){
    //fetch data her, you'll find your prop params in nextProps.params
}

您也可以避免在此处执行此操作,方法是在渲染方法中取消数据获取。

【讨论】:

  • 谢谢@thsorens。将内容从 willMount 更改为 didMount,并在渲染修复它之前添加加载检查。请注意,它想使用 == 而不是 ===。接下来,关于 componentWillReceiveProps,介意 ELI5 它在我的特定情况下使用吗?因为它按原样工作。非常感谢!
【解决方案2】:

您在 componentWillMount 中所做的初始数据集将无助于设置数据,因为您想从 ajax 获取数据。调试 fetchUserID 和 currentUserID 函数是否从本地存储中获取正确的电子邮件和从服务器获取用户 ID。其他都很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-08
    • 2016-04-03
    • 2020-12-21
    相关资源
    最近更新 更多