react 常见问题汇总(不定时更新)

221 阅读3分钟

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. 输入框的注意事项

  1. 输入框如果绑定了state,那么每次输入的时候都会触发组件的更新,如果输入数据不需要回显的话就可以使用useRef进行数据的绑定

3. 状态管理

3.1 React-query

useQuery(用来查询数据),可添加动态参数age,如果age发生变化则query会重新执行

传给queryFn的参数被称为QueryFunctionContext,具体有下面这些属性
  • queryKey:就是配置选项中的queryKey
  • pageParam:当你使用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>
  );
}