api 基础与实践分析
值得 await 的 React.useState
useState 使用很简单,但是为了避免过多的 re-render, 尽可能的少的定义 useState. 在开发的时候,能使用 useRef 代替的尽量使用 useRef 代替。所以规则是:
- 最少的 useState 定义(在 react 中可能要更新批量更新 useState 的 setState)
const page = () => {
// 假如我们的页面里面有很多的 select
const [selectList1, setSelectList1] = useState([])
const [selectList2, setSelectList2] = useState([])
const [selectList3, setSelectList3] = useState([])
const getSelectData = async () => {
const res = awiat request({
url: 'your_path',
options: {
methods: 'get',
params: {count, pageSize: count}
}
})
setSelectList1(res.result.data1) // re-render 1
setSelectList2(res.result.data2) // re-render 2
setSelectList3(res.result.data3) // re-render 3
}
useEffect(() => {
getSelectData()
}. [])
return (
<div>
{selectList1.map((item) => { return item.name})}
{selectList2.map((item) => { return item.title})}
{selectList3.map((item) => { return item.age})}
</div>
)
}
-
不要定义过多的 state
-
state 是在试图展示的更新用的,有些不需要到试图的,放在内存里面就可以了,推荐使用 useRef 保存
-
异步的 setState 的问题,使用异步函数来解决
const page = () => {
const [count, setCount] = useState<number>(1)
return (
<div>
<button onClick={async () => {
await setCount(count + 1);
const res = awiat request({
url: 'your_path',
options: {
methods: 'get',
params: {count, pageSize: count}
}
})
// other
}}>+1</button>
</div>
)
}
所有说 async/await 可能更加般配欧
React.cloneElement
- React.clone API是单独的克隆一个 React 组件或者 DOM 节点。克隆之后我们就可以方便的在上面给 props。
import React from 'react'
const TestClone = (props) => {
const [visiable, setVisiable] = react.useState<boolean>(false);
const {trigger, children} = props;
return (
<div>
{visiable ? <div>
{children}
</div> : null}
{React.cloneElement(trigger, {trigger.props, onClick: () => {
setVisiable(!visiable)
})}
</div>
)
}
export default TestClone;
说明:
- trigger 是一个React 节点,使用 React.cloneElement API 方便的克隆一个这个节点,然后在它基础上添加了新的点击事件。于是当我们点击 trigger 的时候,就会切换 children 节点的现实与隐藏。
这样做的好处,一个节点暴露给外部,状态在内部维护。
总结:cloneElement 是一个很灵活的 API, 得益于第二参数可以用来组合不同的 props。生成一个新的节点。如果你需要对当前的节点 props 进行增删改查操作。使用 cloneElement 是一个很不错的选择。
React 中如何获取子组件的中的数据
场景:我们以偶一个上传组件的封,在上传之前,需要获取 token,其实我们并不关心 token, 只是关心上传之后,服务器返回的数据,这些数据也不需要需要响应到页面。所以可能并不需要使用 useState 定义响应数据
- API React.useImperativeHandle
useImperativeHandle 钩子函数,需要与 React.forward 来进行配合使用。useImperativeHandle 钩子函数接受两个参数,第一个就是传入子组件的 ref, 第二参数是 函数,此函数返回的是我们能在父组件中访问的数据。
使用:
- 父组件中定义 ref
- 在父组件中使用子组件,并绑定 ref 属性
- 子组件配合 forwardRef 使用,拿到 ref
- 绑定 useImperatoveHandle 绑定目标数据
- ref 指向 dom 或者其他子组件的值
import React, {useState, useImperativeHandle } from 'react';
const ChildComponent = React.forwardRef((props, ref) => {
const [data1, setData1] = useState(1)
const onClick = () => {
// your code
}
useImperativeHandle(ref, () => ({
data: data1,
dom1: ref.current,
event1: onClick
}))
return (
<div ref={ref} onClick={onClick}>
react- component - children- data - get methods
</div>
)
})
方便的从组件中拿到,我们想要的数据,而不需要定于多余的 state, setState。
Reactc.Children
问题
- React 为什么要单独提提供操作 React.Children 的 API?
- React.Children 解决了什么问题?
useRef 中定义的数据,会 使得 useEffect 中的 effect 函数,被调用吗?
其实如果我们想让一个页面刷新,其实就是在 useEffect 中只执行一次的,要它强制更新一次。
- statas 是会更新试图
- ref 的变化,理论上也使得副作用重新执行