问题描述
今天里面写项目的时候出现了一个问题,就是根组件异步获取的数据需要使用React的context,把异步获取的数据存储全局的context中,并在子组件中使用这个context的数据,并用获取到的context再次发起一个其他的请求。这个时候就会出现一个问题,异步获取的数据,在有些时候(数据相应比较慢的时候)。子组件拿到的是一哥空对象,但是我们需要基于这个对象再次发起请求,但是拿到的是一个空对象。
解决
我进行了一次模拟。结构如下.
<app>
<child></child>
</app>
首先我们先创建一个context的文件,把所有 有关context的内容封装起来。
//globleContext.js
import React from "react";
export const globalData = {
a: "dawbdhawbj"
}
export const globleContext = React.createContext(globalData)
我在app组件中进行第一次数据的请求如下
//app.js
import React from "react";
import Child from "./compons/child";
import Axios from "axios";
import {
globleContext , globalData } from "./globleContext";
const {
Provider } = globleContext;
class App extends React.Component {
constructor(){
super()
this.state = {
a: globalData.a
}
}
componentDidMount(){
Axios.get("http://localhost:3000/article/test").then(res => {
this.setState({
axiosData : res.data.data
})
console.log(res.data)
//undefind
//有些时候会返回我想要的值,但是有写时候会返回一个空对象
//(我测试接口用的是node写的,定时器2s在返回数据。所以这里是undefind)
})
}
render(){
return (
<div className="App">
<Provider value={
this.state.axiosData}>
<Child></Child>
</Provider>
</div>
);
}
}
export default App;
下面我们在看看child.组件。这里我写了两种方式。一种函数组件中/一种class形式的。
//child.js (函数组件)
import React,{
Component , useEffect ,useState } from "react";
import {
globleContext } from "../Globle";
import Axios from "axios";
function child(params) {
const [TreeData,setTreeData] = useState([])
const context = React.useContext(globleContext)
console.log(context)
useEffect( () => {
console.log("数据变化了")
if(context){
if(TreeData.length == 0){
Axios.get("http://localhost:3000/article/testapi/").then(res => {
console.log(res,"这是数据222")
setTreeData(res.data.data)
})
};
}
})
return (
<div>
这是child组件顶顶顶:{
TreeData}
</div>
)
}
// child.contextType = globleContext;
export default child;
import {
Component } from "react";
import {
globleContext } from "../Globle";
import Child from "./child";
import Axios from "axios";
class tree extends Component {
constructor(){
super()
this.state = {
TreeData:[]
}
}
componentDidMount(){
}
componentDidUpdate(prevProps,prevState){
if(this.context){
if(this.state.TreeData.length == 0){
Axios.get("http://localhost:3000/article/testapi/").then(res => {
this.setState({
TreeData:res.data.data
})
})
};
}
}
render() {
return (
<div>
父组件:{
this.context ? "数据来了" : "目前没有数据"}
{
/* <Child></Child> */}
<br/>
{
this.state.TreeData}
</div>
);
}
}
tree.contextType = globleContext
export default tree;
这里可以看到,我使用了 componentDidUpdate ,这里我在componentDidUpdate的使用了if判断。因为每次this.setState()都会触发componentDidUpdate这个方法。因此我们在componentDidUpdate 中使用 this.setState() 就会无限循环。所以我们使用if来进行控制。