关于React Hooks使用时函数render的问题

React Hooks

前言

在使用函数组件时,当组件的state(使用hook获得的)或者props发生变化时会引起函数组件的重新执行和渲染。

一、有可能造成re-renders问题

App.js

function App() {
  const [total, setTotal] = useState(1);
  console.log("app rendered");
  console.log("total", total);
  // debugger
  const isOnline = useTest(total);
  // console.log(isOnline);
  return (
    <div className="App">
      <button onClick = {()=>{setTotal(total + 1)}}>total</button>
      <p>{total}total</p>
      {/* {useMemo(()=> {
        return <Test />
      }, [])} */}
      {isOnline ? <Test /> : null}
    </div>
  );
}

export default App;

useTest.js

import {useState} from "react";

export default function useTest(id) {
    const [isOnline, setIsoline] = useState(false);
    if (id % 2 === 0) {
        setIsoline(!isOnline);
    }
    console.log("useTest执行了");
    return isOnline;
}

初始值若为1,没有问题
当点击按钮,total变为2,因为return的组件中使用了total,因此会引起页面的重新渲染。函数组件在重新渲染的过程中会把函数重新执行一遍,这就造成了会再次执行useTest(total),这样就会造成死循环。

二、函数组件中父组件如何获取子组件的实例或者DOM元素

使用useImperativeHandleforwardRef

1.父组件

function App() {
  const [total, setTotal] = useState(1);
  console.log("app rendered");
  console.log("total", total);
  const parentRef = useRef();
  // debugger
  // const isOnline = useTest(1);
  // console.log(isOnline);
  return (
    <div className="App">
      <button onClick = {()=>{setTotal(total + 1)}}>total</button>
      <p>{total}total</p>
      {/* {useMemo(()=> {
        return <Test />
      }, [])} */}
      <Count></Count>
      <FancyInput ref={parentRef}></FancyInput>
      <button onClick={() => {parentRef.current.focus()}}></button>
    </div>
  );
}

在父组件中,使用useRef()创建一个ref用来保存子组件中的ref,通过子组件中的ref属性传进去。
至于为什么要使用useRef()来保存子组件中的ref,因为函数组件每次渲染时都会执行函数,若是通常申请的变量则会重新赋值,但是钩子函数就会把变量挂载到组件APP实例上?

2.子组件

import {useRef, useImperativeHandle, forwardRef} from "react";

function FancyInput(props, parentRef) {
    const inpuRef = useRef();
    useImperativeHandle(parentRef, () => ({
        focus: () => {
            inpuRef.current.focus();
        }
    }))

    return <input ref={inpuRef}></input>
}
FancyInput = forwardRef(FancyInput);
export default FancyInput;

子组件完成的任务是拿到parentRef,将inputref的方法挂载到parentRef上。(理解可能不准确,后续再查资料)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值