最近我的项目用了 umi3+react17+antd pro5
我的项目中遇到的useState的坑
1.useState不适宜简单对象的更改
因为useState不能像setState那样进行合并更新,当应用useState第二个参数进行数据更新的时候,必须传入一个残缺的构造,而不仅仅只是扭转的那一部分。
2.useState异步回调的问题
当应用usestate对数据进行更新,并不能立即获取到最新的数据。
const [name, setName] = useState('dx');const handleTest = () => { console.log(name) // dx setName('dx1') console.log(name) // dx}
解决方案
一、配合useEffect应用
const [name, setName] = useState('dx');const handleTest = () => { console.log(name) //dx setName('dx1') console.log(name)//dx} useEffect(() => { console.log(name) //dx1},[name])
二、创立一个新的变量保留最新的数据
const [name, setName] = useState('dx');const handleTest = () => { console.log(name) //dx const newName = "dx1" setName(newName) console.log(newName) //dx1}
3.依据hook的规定,应用useState的地位有限度
- 仅顶层调用 Hook :不能在循环,条件,嵌套函数等中调用useState()。
- 在多个useState()调用中,渲染之间的调用程序必须雷同。
- 仅从React 函数调用 Hook:必须仅在函数组件或自定义钩子外部调用useState()。
4.应用useState,回调函数模式更改数据
const [a, setA] = useState({c:1})/** oldA为之前的a,return为设置的新值 */setA((oldA) => { return {c: oldA.c + 1}})
5.useState存入的值只是该值的援用(援用类型)
const textObj = {name:'dx'}const [useState1, setUseState1] = useState(textObj )const [useState2, setUseState2] = useState(textObj )/** usestate的操作不要放在函数的最外层,这里只是简略的代码展现,你能够将set操作放在某个函数外面 */setUseState1((oldUseState1) => { oldUseState1.age = 18 return {...oldUseState1}})useEffect(() => { /** 扭转一个会导致两个都扭转,深浅拷贝的问题 */ console.log(useState1) // {name: "dx", age: 18} console.log(useState2) // {name: "dx", age: 18}},[useState1])
解决的计划
const textObj = {name:'dx'}const [useState1, setUseState1] = useState(textObj )const [useState2, setUseState2] = useState(JSON.parse(JSON.stringify(textObj)))/** usestate的操作不要放在函数的最外层,这里只是简略的代码展现,你能够将set操作放在某个函数外面 */setUseState1((oldUseState1) => { oldUseState1.age = 18 return {...oldUseState1}})useEffect(() => { /** 扭转一个会导致两个都扭转,深浅拷贝的问题 */ console.log(useState1) // {name: "dx", age: 18} console.log(useState2) // {name: "dx"}},[useState1])
6.useState,如果保留援用数据,useEffect检测不到变动?
const textObj = {name:'dx'}const [useState1, setUseState1] = useState(textObj)/** usestate的操作不要放在函数的最外层,这里只是简略的代码展现,你能够将set操作放在某个函数外面 */setUseState1((oldUseState1) => { oldUseState1.age = 18 return oldUseState1}useEffect(() => { console.log(useState1) },[useState1])//后果是没有任何反馈
解决办法
const textObj = {name:'dx'}const [useState1, setUseState1] = useState(textObj)/** usestate的操作不要放在函数的最外层,这里只是简略的代码展现,你能够将set操作放在某个函数外面 */setUseState1((oldUseState1) => { oldUseState1.age = 18 /** 返回一个新的对象,useEffectc能力检测失去 */ return {...oldUseState1}}useEffect(() => { console.log(useState1) // {name: "dx", age: 18}},[useState1])
7.useState无奈保留一个函数
你是否尝试着将函数的援用作为一个变量保留到useState中去呢?
比方:
const testFunciton1 = () => { console.log({name: 'dx',age: '18'})}/** usestate保留函数测试 */const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1);useEffect(() => { console.log(stateFunction)// {name: 'dx', age: 18}}, [stateFunction])
代码中从未调用过testFunciton1 ,后果testFunciton1却被执行了
useEffect打印进去的却是一个undefined。
略微改变一下代码,再测试
const testFunciton1 = () => { console.log({name: 'dx',age: '18'}) return { name: 'yx', age: '17' }}/** usestate保留函数测试 */const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1);useEffect(() => { console.log(stateFunction)// {name: 'dx', age: 18} // {name: 'yx', age: 17}}, [stateFunction])
很显著,在useState中,函数会主动调用,并且保留函数返回的值,而不能保留函数自身。
解决的计划
应用useState不能保留函数,那么能够应用useCallback这个hook。
/** useCallback,应用参数与useEffect统一 */const testFunction = useCallback(() => { // useCallback返回的函数在useCallbak中构建 const testFunciton1 = () => { console.log({ name: 'dx', age: '18' }); return { name: 'yx', age: '17', }; }; return testFunciton1;}, []);useEffect(() => { console.log(testFunction());// 打印的是函数}, [testFunction]);