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

时间:2017-10-30 20:15:03

标签: javascript reactjs reactjs-flux

我几个小时以来一直坚持这个问题。我想实现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。为什么会这样?我做错了什么?

4 个答案:

答案 0 :(得分: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;
    }
}

如果这是真的,我建议在BucketApploading时不要呈现true。将标志存储起来并在BucketApp中使用它以防止渲染(显示加载器)。

答案 1 :(得分:1)

它返回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 }) 
       })
    }

答案 2 :(得分:0)

我想这是因为你的组件在结束异步提取之前呈现自己。换句话说,您未定义,并且在完成fetch后(当您的商店更新时)获得结果时,您的组件不会更新。您可以应用上述技术,也可以使用Redux。在Redux中,如果存储更新,则会导致以某种方式与Redux存储连接的所有组件的更新。

答案 3 :(得分:0)

为解决此问题,我在组件状态上加载了初始数据,并在承诺被解决后侦听了componentDidMount上的发射以更新状态。下面是带有您的代码的示例。

//存储

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