常见的钩子函数:useState、useEffect
useState作为最常见的一个hook,在使用中总是会出现各种坑,最明显的就是 useState 更新异步的问题。
import React, { useState, useEffect } from 'react';
import styles from './index.less';
export default function index({ content = {} }) {
const [data, setData] = useState([]);
useEffect(() => {
if (content !== null) {
const myModityData = content.title.split('***');
setData(myModityData);
}
}, [content.title]);
return (
<div className={styles.home_box}>
<div className={styles.title}>{data[0]}</div>
<div className={styles.titleBottom}>{data[1]}</div>
<p className={styles.des}>{content.des}</p>
</div>
);
}
这是因为React里事件分为合成事件和原生事件,合成事件和钩子函数都是异步的,原生事件是同步的。因为useState是异步事件,所以会出现不能及时获取到最新值的情况。
useState 返回的更新状态方法是异步的,要在下次重绘才能获取新值。不要试图在更改状态之后立马获取状态。
注意:useEffect的第二个参数,我表明监听content.title但还是不行,因为在React的函数组件中使用useState进行数据存储,导致数据异步,不能及时获取当前最新的数据。
import React, { useState, useEffect, useRef } from 'react';
const Index = () => {
const [info, setInfo] = useState()
const infoRef = useRef()
useEffect(() => {
infoRef.current = info
}, [info])
}
const [data, setData] = useState(1)
setData(data + 1)
const [data, setData] = useState(0)
setData((prev) => prev + 1); // prev 是data 改变之前的值,return 返回的值会作为新状态覆盖data
原文链接:React hooks中 useState踩坑——异步问题
控制台报错:
中文解释:警告:超过了最大更新深度。当组件在useEffect内部调用setState时,可能会发生这种情况,但useEffect要么没有依赖关系数组,要么依赖关系在每次渲染时都会发生变化。
完整代码:
const UAVEdge = (props) => {
const { UAVEdgeModel, dispatch } = props;
const { productLists, typeId, page } = UAVEdgeModel;
const [data, setData] = useState(productLists);
const myRef = useRef();
useEffect(() => {
myRef.current = data;
const myDeleteData = myRef.current.slice(0, 1);
setData(myDeleteData);
}, [data]);
useEffect(() => {
dispatch({
type: 'UAVEdgeModel/getProductList',
});
}, []);
return (
<>
<Banner content={uavDate} />
<Content content={data} />
<Content02 content={productLists} />
{/* */}
</>
);
};
export default connect(({ UAVEdgeModel }) => ({
UAVEdgeModel,
}))(UAVEdge);
控制台报错:
中文解释:
未捕获错误:重新渲染过多。React限制渲染次数,以防止无限循环。
代码:
完整代码:
import React, { useState, useEffect } from 'react';
import styles from './index.less';
export default function index({ content = [] }) {
const [data, setData] = useState(content);
setData((prev) => {
const myDeleteData = prev.slice(1, 5);
return myDeleteData
})
return (
<div className={styles.home_box}>
<div className={styles.home_container}>
{data.map((item) => {
return (
<div className={styles.edge_box} key={item.id}>
<div className={styles.boxContainer}>
<img src={item.img} alt="一张图" />
<div className={styles.title}>{item.title}</div>
<p className={styles.des}>{item.des}</p>
</div>
</div>
);
})}
</div>
</div>
);
}
完整代码:
import React, { useState, useEffect, useRef } from 'react';
import styles from './index.less';
export default function index({ content = [] }) {
const [data, setData] = useState(content);
const myRef = useRef();
useEffect(() => {
const myDeleteData = data.slice(1, 5);
myRef.current = myDeleteData;
}, [data]);
return (
<div className={styles.home_box}>
<div className={styles.home_container}>
{myRef.current?.map((item) => {
return (
<div className={styles.edge_box} key={item.id}>
<div className={styles.boxContainer}>
<img src={item.img} alt="一张图" />
<div className={styles.title}>{item.title}</div>
<p className={styles.des}>{item.des}</p>
</div>
</div>
);
})}
</div>
</div>
);
}
思路:组件传参的时候,传数据
控制台报错:
中文解释:
需要独一无二的key。可是我明明已经给了,为什么?
接口返回的数据:
函数组件传参,代码:
函数组件传参,完整代码:
const UAVEdge = (props) => {
const { UAVEdgeModel, dispatch } = props;
const { productLists, typeId, page } = UAVEdgeModel;
useEffect(() => {
dispatch({
type: 'UAVEdgeModel/getProductList',
});
}, []);
return (
<>
<Banner content={uavDate} />
<Content content={[productLists[0] || {}]} />
<Content02 content={productLists} />
{/* */}
</>
);
};
export default connect(({ UAVEdgeModel }) => ({
UAVEdgeModel,
}))(UAVEdge);
思路:把数据处理干净传过去,使用useRef()处理数据
代码:
完整代码:
const GroundEdge = (props) => {
const { GroundEdgeModel, dispatch } = props;
const { productLists, typeId, page } = GroundEdgeModel;
const [data, setData] = useState(productLists);
const myRef = useRef()
useEffect(() => {
const myDeleteData = data.slice(0,1);
myRef.current = myDeleteData
}, [data]);
useEffect(() => {
dispatch({
type: 'GroundEdgeModel/getProductList',
});
}, []);
return (
<>
<Banner content={groDate} />
<Content content={myRef.current} />
<Content02 content={productLists} />
{/* */}
</>
);
};
export default connect(({ GroundEdgeModel }) => ({
GroundEdgeModel,
}))(GroundEdge);
完整代码:
const OnboardEdge = (props) => {
const { OnboardEdgeModel, dispatch } = props;
const { productLists, typeId, page } = OnboardEdgeModel;
const [info, setInfo] = useState(productLists);
let infoRef = useRef();
useEffect(() => {
if (productLists !== null) {
const myModityData = info.map((item) => {
return {
...item,
title: item.title.split('***'),
};
});
infoRef.current = myModityData[0];
}
}, [info]);
useEffect(() => {
dispatch({
type: 'OnboardEdgeModel/getProductList',
});
}, []);
return (
<div className={styles.home_box}>
<Banner content={onbDate} />
{/* */}
<PageTitleThreeC content={infoRef.current} />
<Content01 content={productLists[0]} />
<Content02 content={productLists} />
{/* */}
</div>
);
};
export default connect(({ OnboardEdgeModel }) => ({
OnboardEdgeModel,
}))(OnboardEdge);
之前解决了那么多,但useState在项目实际中依然没有解决。
终极简单思路:处理“干净的”数据传给组件,再传递的时候进行一个数组对象的截取react适用,vue没有实践过。
处理前:
处理后:
字符串转数组:
期待把后端的数据title字段进行一个split()截取
import React, { useState, useEffect, useRef } from 'react';
import styles from './index.less';
export default function index({ content = {} }) {
let arr = [];
if (content.title) {
let title = content.title;
arr = title.split('***');
}
return (
<div className={styles.home_box}>
<div className={styles.title}>{arr[0]}</div>
<div className={styles.titleBottom}>{arr[1]}</div>
<p className={styles.des}>{content.des}</p>
</div>
);
}
大道求简。在写的过程中,一点一点完善,发现到了最后,有更加简单的方法,根本不用走那一套。
你要问我有没有意义,仁者见仁。