1. 父组件更新会导致子组件更新
解决办法:
1.1 使用Memo
暴露子组件时候使用export default React.Memo(App), 这样只有props和自身state更新时候才会更新
1.2 使用useCallback
// 父组件传递给子组件的方法使用 useCallback包裹(解决props非必要更新导致的子组件更新)
const getList = useCallback(()=>{},[])
// 注意事项: 依赖项一定要写,否则函数内使用到的数据永远不会更新
1.3 使用useMemo(父组件传递给子组件的data数据导致的更新)
// 如果是固定数据可以写在方法外
const data ={}
// 如果是和组件数据处理有关的则使用useMemo包裹,只要依赖项没变就不会变化
const data = useMemo(() => {
return arr.map((item) => item.id);
}, [arr]);
const App:React.FC=()=>{
<Son data={data} />
}
1.4 使用useRef或者useEffect
// 即使使用了上述方法,但是存在依赖项state频繁变化导致子组件更新的情况
const [count,setCount] = useState<number>(0)
const data = useMemo(() => {
return count;
}, [count]);
const App:React.FC=()=>{
<Button onClick = {()=>setCount(count++)}/>
<Son count={data} />
}
// 使用useRef 因为useRef 变化不会导致组件更新,且变化时同步的
const count = useRef<number>(0)
const App:React.FC=()=>{
<Button onClick = {()=>count.current++}/>
<Son count={count} />
}
// 使用useEffect进行监听数据变动来处理下一步逻辑
// 只传递方法,不传递count,这样子组件也不会变动
const [count,setCount] = useState<number>(0)
useEffect(()=>{
console.log(count)
},[count])
const App:React.FC=()=>{
<Button onClick = {()=>setCount(count++)}/>
<Son setCount={setCount} /> // 内部调用进行count的处理
}
2. 输入框的注意事项
- 输入框如果绑定了state,那么每次输入的时候都会触发组件的更新,如果输入数据不需要回显的话就可以使用
useRef进行数据的绑定
3. 状态管理
3.1 React-query
useQuery(用来查询数据),可添加动态参数age,如果age发生变化则query会重新执行
传给queryFn的参数被称为QueryFunctionContext,具体有下面这些属性
queryKey:就是配置选项中的queryKeypageParam:当你使用useInfiniteQuery的时候传递的参数signal:主要就是取消请求meta:配置选项中的meta配置,自定义的一些信息。
import { useQuery, queryCache } from 'react-query';
function App() {
// isFetched 默认是false,查询完改成true
// isLoading 默认false 查询时true,完成变成false
const {data, isLoading, isError,isFetched,refetch} = useQuery(['userData',age], ({queryKey,signal}) => axios.get('/api/user',params:{age}),{
enabled: !!age, // 当age存在时发起请求
staleTime: 10 * 1000,//10秒内数据是新鲜的 默认0 Infinity 永不过期
cacheTime:5*60*1000, //默认5分钟,超过5分钟缓存会被收回 Infinity 永不过期
retry:3, //出错重试次数,默认3
refetchOnWindowFocus:true, // 窗口获取焦点查询数据(缓存已过期的话重新查询)
initialData:{}, // 配置默认数据
keepPreviousData:false, // 默认false,true 则查询结束前保留之前的数据
});
return (
<ul>
{data.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
)
}
- useMutation(通过query的
key值,此处是userData用来改并更新数据)
import { useQuery, queryCache,useMutation } from 'react-query';
function App() {
const { data, isLoading, isError, isFetched } = useQuery('userData', () =>
axios.get('/api/user'),
);
const { mutate } = useMutation(
(userData) => axios.post('/api/user/add', userData),
{
onSuccess: () => {
// 添加接口完成之后,重新获取列表接口
queryCache.invalidateQueries('userData');
},
},
);
return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
<button
onClick={() => {
mutate({name: 'xx', age: xx})
}}
>
增加
</button>
</ul>
);
}