React Flux 通过 API 调用加载初始数据

Posted

技术标签:

【中文标题】React Flux 通过 API 调用加载初始数据【英文标题】:React Flux Loading Initial Data via API Call 【发布时间】:2018-04-11 22:02:31 【问题描述】:

我已经被这个问题困扰了好几个小时了。我想实现 Flux 架构。我正在尝试创建一个 ToDo 列表。但是,我想事先加载一些初始数据。例如在我的 todoStore.js 中:

import  EventEmitter  from "events";

class ToDoStore extends EventEmitter 
    constructor()
        super();
        this.bucket_list = [
            id: 123,
            name: "Hi",
            isCompleted: false
        ]

    

    getAll()
        return this.bucket_list;
    

我这里有一些初始数据,供我的todo.js使用:

import toDoStore from './stores/todoStore'

class BucketApp extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            bucket_list: toDoStore.getAll()
        ;
    

而且这很好用。我有一家商店,基本上是collection,我的component 从中接收数据。但是,现在我想初始化数据库中的数据。所以我更新了我的todoStore.js

class BucketlistStore extends EventEmitter 
    constructor()
        super();
        fetch(url)
            .then(d => d.json())
            .then(d => 
                this.bucket_list = d;
            );
    

    getAll()
        return this.bucket_list;
    

但是,getAll() 返回undefined。为什么会这样?我做错了什么?

【问题讨论】:

【参考方案1】:

既然fetch是异步操作,可能你调用getAll()太早了?这不是一个解决方案,但您可以检查假设:

class BucketlistStore extends EventEmitter 
    constructor()
        super();
        this.loading = true;
        fetch(url)
            .then(d => d.json())
            .then(d => 
                this.loading = false;
                this.bucket_list = d;
            );
    

    getAll()
        console.log(this.loading);
        return this.bucket_list;
    

如果是真的,我建议不要渲染 BucketApploadingtrue。将标志放入存储并在BucketApp 中使用以防止渲染(改为显示加载器)。

【讨论】:

【参考方案2】:

它返回undefined,因为获取数据是异步的,并且在初始化期间this.bucket_list 是未定义的。试试这个:

class BucketlistStore extends EventEmitter 
    constructor()
        super();
        this.bucket_list_promise = fetch(url)
            .then(d => d.json());
    

    getAll()
        return this.bucket_list_promise;
    

然后

import toDoStore from './stores/todoStore'

class BucketApp extends React.Component 
    constructor(props) 
        super(props);
        this.state = 
            loadingData: true,
            bucket_list: null
        ;
    

    componentWillMount()
       toDoStore.getAll().then(result => 
          this.setState( bucket_list: result, loadingData: false ) 
       )
    

【讨论】:

【参考方案3】:

我想这是因为您的组件在结束异步获取之前呈现了自己。换句话说,你得到未定义,当你在完成fetch(当你的商店更新时)得到结果时,你的组件没有更新。您可以应用上述技术,或者您可以使用 Redux。在 Redux 中,如果 store 被更新,它会导致所有与 Redux store 连接的组件的更新。

【讨论】:

【参考方案4】:

为了解决这个问题,我在我的组件状态上加载了初始数据,并在 componentDidMount 上监听 emit 以在 promise 解决时更新状态。下面是您的代码示例。

//存储

import EventEmitter from "events";
let initState = 
  id: 123,
  name: "Hi",
  isCompleted: false,
  loadingData: true
;

class BucketlistStore extends EventEmitter 
  constructor() 
    super();
    fetch(url)
      .then(d => d.json())
      .then(d => 
        const  id, name, isCompleted  = d;
        initState =  id, name, isCompleted, loadingData: false ;
        this.emit("updated");
      );
  

  getAll() 
    return initState;
  


export default new BucketlistStore();

//组件

import React,  Component  from "react";
import toDoStore from "./stores/todoStore";

class BucketApp extends Component 
  constructor(props) 
    super(props);
    this.state = toDoStore.getAll();
  

  updateState = () => 
    const  id, name, isCompleted, loadingData  = toDoStore.getAll();
    this.setState( id, name, isCompleted, loadingData );
  ;

  componentWillMount() 
    toDoStore.on("updated", this.updateState);
  

  componentWillUnmount()
    toDoStore.off("updated", this.updateState);
  

  render() 
    const  id, name, isCompleted, loadingData  = this.state;

    if (loadingData) return <p>Loading...</p>;

    return null; //your code
  

【讨论】:

以上是关于React Flux 通过 API 调用加载初始数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在通量存储中异步加载初始状态?

API 调用后 React/Flux seState 不重新渲染组件

如何在 React.js Flux 架构和 McFly 中使用操作处理 API 调用?

React Flux 从远程服务获取 Api 数据

在 Flux/React.js 中,在哪里初始化 jQuery 插件?

如何使 reactjs/flux/react-router spa 同构?