React中useState如何保存函数

1,181 阅读2分钟

useState如何保存函数

先要明确一个概念:

image.png

image.png

useState右边括号中初始值为类似0这种类型的时候,其左边数组中初始值的类型也就为对应的number类型;

用一句简单的话来说,右边赋什么,左边就是什么,也就是说useState是能存储这些数据的,但是有一种类型除外,就是函数,见下图

image.png

当右边为函数的时候,左边居然为void类型,怎么解决??

image.png

只需将你想要保存的函数作为返回值即可!(其实这里利用了惰性加载,参见例a旁的注解)

  const [fn,setFn ] = React.useState(()=>()=>{});

useState中保存函数的实战与方案

注意比较下面的两个例子:

例a:(注意:useState中的函数一开始渲染的时候回立即执行!就是说useState右边括号中的函数在组件的初始渲染中会立即执行)

image.png

例b:(完成了对函数的保存与更改)

image.png

image.png

image.png

image.png

import React from "react";
import "./styles.css";

export default function App2() {
  const [fn, setFn] = React.useState(() => () => {
    alert("I am init function");
  });

  console.log("fn: ", fn);

  return (
    <div className="App">
      <button onClick={() => setFn(() => () => alert("update function"))}>
        setCallback
      </button>
      <button onClick={fn}> callback </button>
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

image.png

最佳解决方案(使用useRef)

使用useRef解决这个问题的坑:

import React from "react";
import "./styles.css";

export default function App3() {
  const callbackRef = React.useRef(() => {
    alert("I am init function");
  });

  const callback = callbackRef.current

  console.log("callback: ", callback);

  return (
    <div className="App">
      <button onClick={() => (callbackRef.current=() => alert("update function"))}>
        setCallback
      </button>
      <button onClick={callback}> callback </button>
      {/*s12*/}
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

点击callback按钮:

image.png

点击setCallback:

image.png

再次点击callback按钮(发现没有变化,调用的还是原来的函数)

image.png 上面问题的原因是什么?

useRef不是state,用useRef定义的只是普通的变量,不是本组件的状态,useRef这个容器里保存的值改变的时候,state不会改变,故不会触发渲染;

故s12处的callback还是第一次渲染时的callback!怎么解决这个问题??

只要将改变之后的callbackRef.current()重新读取出来即可,而不是读取之前的那个值

import React from "react";
import "./styles.css";

export default function App4() {
  const callbackRef = React.useRef(() => alert("I am init function"));

  const callback = callbackRef.current;

  console.log("callback: ", callback);

  return (
    <div className="App">
      <button
        onClick={() => (callbackRef.current = () => alert("update function"))}
      >
        setCallback
      </button>
      {/*下面一行很重要!!!如果写成callbackRef.current也还是不行,这样读取的还是之前的值,并没有重新读取 */}
      <button onClick={() => callbackRef.current()}> call callback </button>
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

image.png

image.png

image.png

总结

本文主要小结了useState是如何保存函数的,主要是采用柯里化的方式,即类似于如下这种解决方式(主要是将你想要保存的函数作为返回值):

const [fn, setFn] = React.useState(() =>() => {
console.log("I am Currying")
});

至此,又解决了一个useState的坑