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;
如果是真的,我建议不要渲染 BucketApp
而 loading
是 true
。将标志放入存储并在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 调用?