使用ComponentDidMount中的API调用来更新Redux存储使我的组件呈现两次

gkk*_*sch 9 reactjs redux

我是React/Redux的新手.任何帮助都会很棒.我有一个组件,它在ComponentDidMount上进行API调用以获取数据,然后更新我的Redux存储.该组件还使用connect来获取Redux状态,并将其作为props传递给哑组件.

componentDidMount() {
  this.props.dispatch(fetchSite()) //this triggers the api call and updates the redux store.
}

return ( 
  <div>
    <Child
        myprop={this.props.name}
    />
  </div>

export default connect((state) => ({name: state.name}))(Container);
Run Code Online (Sandbox Code Playgroud)

因为componentDidMount在组件呈现后触发,它将呈现,运行api,然后重新呈现,因为api更改了redux状态.这使得组件呈现两次.第一次没有任何数据,然后第二次有来自api的好数据.

有没有更好的办法?

由于我的Child组件基于它传递的props呈现不同的东西,因此它在第一次呈现时会短暂地显示不同的东西.然后,当api更新商店并重新呈现组件时,它会再次显示不同的内容.它是两种不同状态的闪烁.

有没有办法让它只用正确的API数据渲染一次?

Dav*_*lsh 7

让我们考虑一下这里发生了什么.

页面及其所有资产都在浏览器中加载,运行脚本并呈现所有React组件.只有在渲染完成后才能获取数据.所以当然会有一个初始状态,然后是一个加载状态.

那么在数据进入之前,您如何处理应用程序的状态?

您已经表达了您对使用空白数据呈现应用程序的可理解的不喜欢.您可以延迟应用程序的呈现,直到数据到达.但这会导致糟糕的用户体验.在发生任何事情之前,他们可能会在几秒钟内盯着空白页面.

或者有旧的装载技巧.你可能有类似isLoading: true初始状态的东西.这将对应于React组件中的一些可视加载指示器(传统上是旋转的GIF图像).如果您必须通过AJAX加载数据,这肯定是最佳选择.

一个更好的方法

但事情就是这样:你不需要在初始状态下使用AJAX.您可以通过将数据附加到页面来完全避免此延迟.

<!-- place this BEFORE your Redux/React scripts -->
<script>
    // This object must match the shape of your Redux reducer state
    var __INITIAL_DATA__ = {
        todos: [{
            name: "Gather requirements",
            done: false
        }, {
            name: "Write code",
            done: false
        }]
    };
</script>
Run Code Online (Sandbox Code Playgroud)

现在你所需要做的就是在创造时"保湿"你的商店.

const store = createStore(rootReducer, window.__INITIAL_DATA__);
Run Code Online (Sandbox Code Playgroud)