javascript - react : initial render fires before state is set (via ajax)

标签 javascript jquery ruby-on-rails ajax reactjs

我已经设置好让 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 中的 token 来管理 session ——我也是 JS session 的新手。请耐心等待。

主页组件:

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>
    )
}
})

最佳答案

因此,您要做的是在 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
}

您也可以通过在渲染方法中踢数据获取来避免在此处执行此操作。

关于javascript - react : initial render fires before state is set (via ajax),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33538352/

相关文章:

javascript - 如果禁用了 javascript,如何加载外部 css 文件

javascript - 在不影响导航按钮的情况下单击元素外部时尝试关闭移动菜单(删除类)

javascript - Jquery 日期规则在 Firefox 和 IE 中不起作用

ruby-on-rails - 设计错误: email can't be blank

javascript - 如何使用 Protractor 配置文件的参数来选择步骤?

javascript - 如何在 Javascript 中制作自定义对象?

javascript - 将部分文本加粗(直到第一个 '/' )

jquery 如果 div 中所有文本都可见

ruby-on-rails - after_destroy 删除类别

ruby-on-rails - 用于测试 Ruby Gem 的嵌套项目