简体   繁体   English

React-在渲染中更新内容的正确方法

[英]React - Proper way to update content in render

Normally I am quite confident with the principles of ReactJS and rendering dynamic content. 通常,我对ReactJS的原理和渲染动态内容很有信心。 I could really do with some help however. 我确实可以提供一些帮助。

The problem started with the fact that I have a page called Feed. 问题始于我有一个称为Feed的页面。 This feed should display a list of images fetched from an API. 该供稿应显示从API提取的图像列表。

I need this API to be secured by a token passed as a header. 我需要通过作为标头传递的令牌来保护此API。

In App.js, here is the relevant portion of code which checks if a user is logged in and restricts access to feed unless they are. 在App.js中,这是代码的相关部分,该部分检查用户是否登录并限制对feed的访问,除非他们登录。 The token is saved to state and passed into Feed as a prop. 令牌将保存为状态并作为道具传递到Feed中。

authenticate = () => {
      const token = localStorage.getItem("token");
      validateToken(token)
      .then(() => {
        this.setState({ authenticated: true, token: token  });
      })
      .catch(() => {
        this.setState({ authenticated: false, token: false });
      })
  }

  render() {
        let privateRoutes = null;
        if (this.state.authenticated) {
            privateRoutes =(
                <div>

                    <Route exact path="/feed" 
                    render={(props)=>{
                        return (
                        <Feed token={this.state.token}/>)}} />    

                     <Route exact path="/profile/:username" 
                        render={(props)=>{
                          return (
                           <Profile data={props}/>)}} />         
                </div>
            );
        }

In Feed, I then call the API to get the images passing in this token. 然后,在Feed中,我调用API以获取通过此令牌传递的图像。 Here is where the problem is, in Feed, when I console log 'this.props.token', it is null for a split second before it is what was sent from app.js. 这是问题所在,在Feed中,当我控制台登录“ this.props.token”时,在从app.js发送来的消息之前的一瞬间它为null。

This means I cannot call the API in componentDidMount as the token is initially null. 这意味着我无法在componentDidMount中调用API,因为令牌最初为null。 Furthermore this means I cannot set the state of the posts as I am in render() at this point. 此外,这意味着我此时无法像在render()中那样设置帖子的状态。

Here is the feed code: 这是供稿代码:

    render() {
        const token = this.props.token;
        let posts = []; // should be updated by below
        if (token !== false) {
            loadFeedForUser(token).then((response) => {
                posts = response;
                console.log(posts); // logs successfully
            })
            .catch(() => {
                posts = [];
            })
        }
        return ( 
            <div className="App">

                <div className="content">
                    <div className="feed">
                    { Object.values(posts).map((post, i) => {
                        console.log(post);
                        return (
                            <Post/> // This does not run as posts still empty array
                        )
                    })}

In the HTML, the object for loop never runs as the posts array is empty as it has not registered as being updated by the API. 在HTML中,for循环的对象永远不会运行,因为posts数组为空,因为它尚未注册为由API更新。

What is wrong with my architecture here? 我这里的架构有什么问题? It does not feel good at all. 一点感觉都不好。

Thanks. 谢谢。

Can anybody suggest where I can improve this? 有人可以建议我可以改善这一点吗? I need to pass the token from app.js only when authenticated and then get all the images. 我仅需要通过身份验证时才通过app.js传递令牌,然后获取所有图像。

The component is mounting before the prop is ready. 道具准备就绪之前,组件已安装。 This is a very common scenario, which is a big reason why I prefer hooks. 这是一个非常常见的情况,这是为什么我更喜欢钩子的重要原因。 To fix it you should use the componentDidUpdate lifecycle method, something like 要修复它,您应该使用componentDidUpdate生命周期方法,例如

componentDidUpdate(prevProps, prevState, snapshot) {
  if (props.token && props.token !== prevProps.token) {
    makeApiCall(props.token)
  }
}

You'll also need to have similar logic in your componentDidMount just in case it does have the token value during mount. 您还需要在componentDidMount具有类似的逻辑,以防万一安装过程中确实具有令牌值。 Otherwise it won't make the initial call. 否则它将无法进行初始呼叫。

As a hook, this is all the code that would be needed: 作为一个钩子,这是所有需要的代码:

useEffect(() => {
   makeApiCall(props.token)
}, [props.token])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM