组件中的 API - 函数组件
React 函数组件 API
React 中的函数组件主要有以下 API:
代码举例说明:
1. useState
useState:用于在函数组件中声明和管理状态。
React 中的useState
是一个 Hook,用于在函数组件中添加内部状态。它接受一个初始状态作为参数,并返回一个包含两个元素的数组:当前状态和一个用于更新状态的函数。
基本语法
使用useState
的基本语法如下:
import React, { useState } from 'react';
function App() {
const [state, setState] = useState(initialState);
// 在这里可以使用state和setState进行操作
return (
// 渲染组件
);
}
在这个例子中,initialState
是状态的初始值,state
是当前状态,setState
是一个用于更新状态的函数。当调用setState
时,React 会重新渲染组件以反映新的状态。
案例: 1.1
// 案例: 1.1. React 函数组件 useState
const React = window.React;
const { useState } = React;
const { createRoot } = ReactDOM;
const App = () => {
const [count, setCount] = useState(0);
return (
<p>
useState-{count}-<button onClick={() => setCount(count + 1)}>累加</button>
</p>
);
};
createRoot(document.getElementById("app1")).render(<App />);
2. useEffect
useEffect:用于在函数组件中处理副作用,如异步操作、订阅事件等。
React 中的useEffect
是一个 Hook,用于在函数组件中处理副作用。它接受两个参数:一个副作用函数和一个依赖数组。副作用函数是在组件渲染后执行的,而依赖数组则决定了何时执行副作用函数。
基本语法
使用useEffect
的基本语法如下:
import React, { useState, useEffect } from 'react';
function App() {
const [state, setState] = useState(initialState);
useEffect(() => {
// 在这里执行副作用操作
return () => {
// 在这里执行清理操作,例如取消订阅或清除定时器等
};
}, [dependency1, dependency2]); // 依赖数组,当其中的值发生变化时,副作用函数会被重新执行
return (
// 渲染组件
);
}
在这个例子中,useEffect
的第一个参数是一个副作用函数,它会在组件渲染后执行。第二个参数是一个依赖数组,只有当数组中的值发生变化时,副作用函数才会被重新执行。如果依赖数组为空,则副作用函数只会在组件挂载和卸载时执行一次。
案例: 1.2
// 案例: 1.2. React 函数组件 useEffect
const { useState, useEffect } = React;
const { createRoot } = ReactDOM;
const App = () => {
const getTime = () => new Date().toLocaleTimeString();
const [time, setTime] = useState(getTime());
let timerId = null;
const updateTime = () => {
timerId = setInterval(() => setTime(getTime()), 1000);
};
useEffect(() => {
// 回调函数的作用同 componentDidMount
document.title = time;
updateTime();
return () => clearInterval(timerId); // return 作用同 componentWillUnmount
}, [time]); // 第二参数作用是监听 state, 传空数组不监听数据
return <p>useEffect-页面标题-计时器-->{time}</p>;
};
createRoot(document.getElementById("app2")).render(<App />);
3. useContext
useContext:用于在函数组件中使用 Context。
React 中的useContext
是一个 Hook,用于在函数组件中访问 React 的上下文。它接受一个上下文对象作为参数,并返回该上下文的值。
基本语法
使用useContext
的基本语法如下:
import React, { useContext } from 'react';
const MyContext = React.createContext(initialValue);
function App() {
const contextValue = useContext(MyContext);
// 在这里可以使用contextValue进行操作
return (
// 渲染组件
);
}
在这个例子中,MyContext
是一个通过React.createContext
创建的上下文对象,initialValue
是上下文的初始值。useContext
接受MyContext
作为参数,并返回当前上下文的值,即contextValue
。当上下文的值发生变化时,useContext
会重新渲染组件以反映新值。
案例: 1.3
MyContext = createContext()
类似于 vue 中的 provide/inject
// 案例: 1.3. React 函数组件 useContext
const { createRoot } = ReactDOM;
const { createContext, useContext, useState, useEffect } = React;
// 创建 MyProvider 提供者组件, 用于提供数据并传子子组件
const MyContext = createContext();
const MyProvider = ({ children, value }) => (
<MyContext.Provider value={value}>{children}</MyContext.Provider>
);
// 创建 Child 消费者组件, 用于接收数据
const Child1 = () => {
const value = useContext(MyContext);
return <span>{value}</span>;
};
const Child2 = () => {
const value = useContext(MyContext);
return <span>{value}</span>;
};
// 将 Child1 包装在 MyProvider 组件中, 当 value 变化时, 所有包装的 Child 都会更新
const App = () => {
const [value, setValue] = useState(Math.random());
let timerId = null;
const update = () => {
timerId = setInterval(() => setValue(Math.random()), 2000);
return () => clearInterval(timerId);
};
useEffect(() => update(), [value]);
return (
<div>
<MyProvider value={value}>
useContext-value-
<Child1 />-<Child2 />
</MyProvider>
</div>
);
};
createRoot(document.getElementById("app3")).render(<App />);
4. useReducer
useReducer:用于在函数组件中管理复杂的状态逻辑。
React 中的useReducer
是一个 Hook,用于在函数组件中处理复杂的状态逻辑。它接受两个参数:一个 reducer 函数和一个初始状态。reducer 函数是一个纯函数,用于根据当前状态和传入的 action 来生成新的状态。
基本语法
使用useReducer
的基本语法如下:
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
// 在这里可以使用state和dispatch进行操作
return (
// 渲染组件
);
}
在这个例子中,initialState
是状态的初始值,reducer
是一个纯函数,用于根据当前状态和传入的 action 来生成新的状态。useReducer
返回一个包含两个元素的数组:当前状态和一个用于派发 action 的函数。当调用dispatch
时,React 会调用reducer
函数并传入当前状态和传入的 action,然后根据返回的新状态更新组件。
案例: 1.4
作用类似 Vuex 和 Pinia
// 案例: 1.4. React 函数组件 useReducer
const { createRoot } = ReactDOM;
const { useReducer } = React;
const App = () => {
const reducer = (state, action) => {
console.log("useReducer", state, action);
switch (action.type) {
case "increment":
return state + 1;
case "decrement":
return state - 1;
default:
return state;
}
};
let initialState = 0;
const [state, dispatch] = useReducer(reducer, initialState);
return (
<p>
useReducer-{state}-
<button onClick={() => dispatch({ type: "increment" })}>加</button>
<button onClick={() => dispatch({ type: "decrement" })}>减</button>
</p>
);
};
createRoot(document.getElementById("app4")).render(<App />);
5. useCallback
useCallback:用于在函数组件中缓存函数,避免不必要的重新渲染。
React 中的useCallback
是一个 Hook,用于在函数组件中缓存函数的引用。它接受两个参数:需要缓存的函数和依赖项数组。当依赖项数组中的某个值发生变化时,useCallback
会返回一个新的函数引用;否则,它会返回之前的函数引用。
基本语法
使用useCallback
的基本语法如下:
import React, { useState, useCallback } from "react";
function ChildComponent({ onClick }) {
return <button onClick={onClick}>点击我</button>;
}
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<h1>计数器: {count}</h1>
<ChildComponent onClick={handleClick} />
</div>
);
}
export default ParentComponent;
在这个例子中,ParentComponent
有一个状态count
和一个处理函数handleClick
。我们将handleClick
传递给子组件ChildComponent
作为onClick
属性。通过使用useCallback
,我们确保只有在count
发生变化时,handleClick
才会更新。这样可以避免不必要的子组件重新渲染,提高性能。
案例: 1.5
// 案例: 1.5. React 函数组件 useCallback
const { createRoot } = ReactDOM;
const { useState, useCallback } = React;
const Child = ({ onClick }) => {
return <button onClick={onClick}>useCallback-点击</button>;
};
const App = () => {
const [count, setCount] = useState(0);
const onClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<p>
<span>useCallback-计数器-{count}-</span>
<Child onClick={onClick} />
</p>
);
};
createRoot(document.getElementById("app5")).render(<App />);
6. useMemo
useMemo:用于在函数组件中缓存计算结果,避免不必要的重新计算。
useMemo
是 React 提供的一个 Hook,它用于优化那些因为依赖值的小变化而导致的不必要的重新计算。这个 Hook 特别适合于那些执行成本较高的计算,例如计算大量数据的函数或者请求,我们不希望这些操作在依赖值每次微小变化时都执行一次。
基本语法
useMemo
接受两个参数:一个“记忆”的函数和一个依赖项数组。只有当依赖项数组中的某个值发生变化时,useMemo
才会调用该函数并缓存其结果。如果依赖项没有变化,它会返回上一次调用的结果,而不会再次调用该函数。
以下是 useMemo
的基本使用示例:
import React, { useState, useMemo } from "react";
function ExpensiveCalculation({ inputValue }) {
// 假设这是一个高成本的计算函数
return inputValue.length * 2;
}
function App() {
const [inputValue, setInputValue] = useState("");
const expensiveResult = useMemo(() => {
return ExpensiveCalculation({ inputValue });
}, [inputValue]); // 仅当 inputValue 改变时重新计算
return (
<div>
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
{/* 使用计算结果 */}
<p>计算结果: {expensiveResult}</p>
</div>
);
}
export default App;
在这个例子中,ExpensiveCalculation
是一个执行成本较高的函数,它依赖于 inputValue
。通过使用 useMemo
,我们可以确保只有在 inputValue
改变时,才会重新计算 expensiveResult
。这有助于避免不必要的性能开销。
案例: 1.6
类似 Vue 中的 computed
// 案例: 1.6. React 函数组件 useMemo
const { createRoot } = ReactDOM;
const { useState, useMemo } = React;
const CalcFoo = (v) => v.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); // 计算耗时操作
const App = () => {
const [count, setCount] = useState(10000);
const resultValue = useMemo(() => CalcFoo(count), [count]); // 依赖 count 变化
return (
<p>
<span>useMemo-千分符-{resultValue}</span>-
<input value={count} onChange={(e) => setCount(e.target.value)} />
</p>
);
};
createRoot(document.getElementById("app6")).render(<App />);
7. useRef
useRef:用于在函数组件中创建和访问 ref。
基本语法
useRef
是 React 提供的一个 Hook,用于在函数组件中创建和访问可变的引用。它返回一个可变的 ref
对象,该对象具有一个 current
属性,可以用来存储和访问任何类型的值。
以下是一个简单的示例:
import React, { useRef } from "react";
function MyComponent() {
const myRef = useRef(null);
return (
<div>
<input ref={myRef} />
<button onClick={() => console.log(myRef.current)}>
Log input value
</button>
</div>
);
}
在这个例子中,我们使用 useRef
创建了一个名为 myRef
的引用,并将其分配给了一个输入框。然后,我们在按钮的点击事件处理程序中使用 console.log
打印了输入框的值。由于 myRef
是一个可变的引用,因此我们可以在组件的生命周期内随时更新其值。
案例: 1.7
类似 Vue 中的 ref
// 案例: 1.7. React 函数组件 useRef
const { createRoot } = ReactDOM;
const { useRef } = React;
const App = () => {
const myRef = useRef(null);
return (
<p>
useRef-
<input ref={myRef} />-<button onClick={() => alert(myRef.current)}>alert(input)</button>
</p>
);
};
createRoot(document.getElementById("app7")).render(<App />);
8. forwardRef
forwardRef:用于在父组件中访问子组件的 ref。
基本语法
forwardRef
是 React 提供的一个高阶组件(HOC),用于在父组件中访问子组件的 ref。它允许你将 ref 转发给子组件,这样你就可以在父组件中直接操作子组件的实例。
以下是一个简单的示例:
import React, { forwardRef } from "react";
const ChildComponent = forwardRef((props, ref) => {
return <input ref={ref} />;
});
function ParentComponent() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<ChildComponent ref={inputRef} />
<button onClick={handleClick}>Focus input</button>
</div>
);
}
在这个例子中,我们使用 forwardRef
创建了一个名为 ChildComponent
的子组件。然后,我们在 ParentComponent
中使用 useRef
创建了一个名为 inputRef
的引用,并将其分配给 ChildComponent
。当点击按钮时,我们调用 inputRef.current.focus()
方法来聚焦输入框。
案例: 1.8
// 案例: 1.8. React 函数组件 forwardRef
const { createRoot } = ReactDOM;
const { forwardRef } = React;
// 高阶函数包装子组件, 用于 ref 传参
const ChildInput = forwardRef((props, ref) => (
<input ref={ref} style={{ height: "20px" }} />
));
const App = () => {
const inputRef = useRef(null);
const onFocus = () => inputRef.current.focus();
return (
<p>
forwardRef-
<ChildInput ref={inputRef} />-<button onClick={onFocus}>聚焦输入框</button>
</p>
);
};
createRoot(document.getElementById("app8")).render(<App />);
9. useImperativeHandle
useImperativeHandle:用于在函数组件中暴露自定义的 ref 属性。
基本语法
useImperativeHandle
是 React 提供的一个 Hook,用于在父组件中操作子组件的实例。它接受两个参数:一个 ref 和一个函数,该函数返回一个对象,该对象包含要暴露给父组件的方法和属性。
以下是一个简单的示例:
import React, { useRef, forwardRef, useImperativeHandle } from "react";
const ChildComponent = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focusInput: () => inputRef.current.focus();
}));
return <input ref={inputRef} />;
});
const ParentComponent = () => {
const childRef = useRef(null);
const handleClick = () => childRef.current.focusInput();
return (
<p>
<ChildComponent ref={childRef} />
<button onClick={handleClick}>Focus input</button>
</p>
);
}
在这个例子中,我们使用 forwardRef
将 ChildComponent
的 ref 传递给它。然后,我们在 ChildComponent
中使用 useImperativeHandle
创建一个名为 focusInput
的方法,该方法将焦点设置到输入框上。最后,我们在 ParentComponent
中使用 useRef
创建了一个名为 childRef
的引用,并将其分配给 ChildComponent
。当点击按钮时,我们调用 childRef.current.focusInput()
方法来聚焦输入框。
案例: 1.9
// 案例: 1.9. React 函数组件 useImperativeHandle
const { createRoot } = ReactDOM;
const { forwardRef, useImperativeHandle } = React;
// 高阶函数 forwardRef 包装子组件, 用于 ref 传参
const ChildInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
// useImperativeHandle Hook 用于暴露子组件的实例方法
useImperativeHandle(ref, () => ({
...inputRef,
focus: () => {
console.log("暴露了重新的 focus 方法");
inputRef.current.focus();
inputRef.current.style.color = "red";
},
}));
return <input ref={inputRef} />;
});
const App = () => {
const childRef = useRef(null);
const handleClick = () => childRef.current.focus();
return (
<p>
useImperativeHandle-
<ChildInput ref={childRef} />-<button onClick={handleClick}>聚焦输入框</button>
</p>
);
};
createRoot(document.getElementById("app9")).render(<App />);
10. useLayoutEffect
useLayoutEffect:与 useEffect 类似,但执行时机不同,useLayoutEffect 会在 DOM 更新后同步执行。
基本语法
useLayoutEffect
是 React 提供的一个 Hook,用于在函数组件中执行副作用操作。与 useEffect
不同,useLayoutEffect
的副作用操作会在浏览器完成布局之后同步执行,这可以确保在浏览器绘制之前完成副作用操作。
以下是一个简单的示例:
// 案例: 1.10. React 函数组件 useLayoutEffect
const { createRoot } = ReactDOM;
const { useLayoutEffect } = React;
const App = () => {
useLayoutEffect(
() => console.log("This will run after the browser has completed layout"),
[]
);
return <p>useLayoutEffect-Hello World</p>;
};
createRoot(document.getElementById("app10")).render(<App />);
在这个例子中,我们使用 useLayoutEffect
创建了一个副作用操作,该操作会在浏览器完成布局之后同步执行。由于 useLayoutEffect
的副作用操作会在浏览器绘制之前完成,因此我们可以确保在浏览器绘制之前完成副作用操作。
11. useDebugValue
useDebugValue:用于在开发者工具中显示自定义的调试信息。
基本语法
useDebugValue
是 React 提供的一个 Hook,用于在开发模式下为自定义 Hook 添加调试信息。它接受一个参数,即要显示的调试信息。
以下是一个简单的示例:
// 案例: 1.11. React 函数组件 useDebugValue
const { createRoot } = ReactDOM;
const { useState, useDebugValue } = React;
const useCounter = () => {
const [count, setCount] = useState(0);
console.log(
"在 CDN 模式下 useDebugValue 不会起作用, 只有在开发模式下才会启用"
);
useDebugValue("useCounter", count);
return { count, setCount };
};
const App = () => {
const { count, setCount } = useCounter();
return (
<p>
useDebugValue-count-{count}-
<button onClick={() => setCount(count + 1)}>Increment</button>
</p>
);
};
createRoot(document.getElementById("app11")).render(<App />);
在这个例子中,我们创建了一个名为 useCounter
的自定义 Hook,该 Hook 使用 useState
管理计数器的状态。然后,我们使用 useDebugValue
为该 Hook 添加了调试信息,以便在开发模式下显示当前计数器的值。最后,我们在 MyComponent
中使用 useCounter
来获取计数器的状态和更新方法。
代码与演示
1. 全部代码
点击查看代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>test-react-api-函数组件</title>
<!-- <script src="https://cdn.staticfile.org/react/18.0.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/18.0.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script> -->
<script src="./react.js"></script>
<script src="./react-dom.js"></script>
<script src="./babel.js"></script>
</head>
<body>
<div id="app1"></div>
<div id="app2"></div>
<div id="app3"></div>
<div id="app4"></div>
<div id="app5"></div>
<div id="app6"></div>
<div id="app7"></div>
<div id="app8"></div>
<div id="app9"></div>
<div id="app10"></div>
<div id="app11"></div>
<script type="text/babel">
{
// 案例: 1.1. React 函数组件 useState
const React = window.React;
const { useState } = React;
const { createRoot } = ReactDOM;
const App = () => {
const [count, setCount] = useState(0);
return (
<p>
useState-{count}-
<button onClick={() => setCount(count + 1)}>累加</button>
</p>
);
};
createRoot(document.getElementById("app1")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.2. React 函数组件 useEffect
const { useState, useEffect } = React;
const { createRoot } = ReactDOM;
const App = () => {
const getTime = () => new Date().toLocaleTimeString();
const [time, setTime] = useState(getTime());
let timerId = null;
const updateTime = () => {
timerId = setInterval(() => setTime(getTime()), 1000);
};
useEffect(() => {
// 回调函数的作用同 componentDidMount
document.title = time;
updateTime();
return () => clearInterval(timerId); // return 作用同 componentWillUnmount
}, [time]); // 第二参数作用是监听 state, 传空数组不监听数据
return <p>useEffect-页面标题-计时器-->{time}</p>;
};
createRoot(document.getElementById("app2")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.3. React 函数组件 useContext
const { createRoot } = ReactDOM;
const { createContext, useContext, useState, useEffect } = React;
// 创建 MyProvider 提供者组件, 用于提供数据并传子子组件
const MyContext = createContext();
const MyProvider = ({ children, value }) => (
<MyContext.Provider value={value}>{children}</MyContext.Provider>
);
// 创建 Child 消费者组件, 用于接收数据
const Child1 = () => {
const value = useContext(MyContext);
return <span>{value}</span>;
};
const Child2 = () => {
const value = useContext(MyContext);
return <span>{value}</span>;
};
// 将 Child1 包装在 MyProvider 组件中, 当 value 变化时, 所有包装的 Child 都会更新
const App = () => {
const [value, setValue] = useState(Math.random());
let timerId = null;
const update = () => {
timerId = setInterval(() => setValue(Math.random()), 2000);
return () => clearInterval(timerId);
};
useEffect(() => update(), [value]);
return (
<div>
<MyProvider value={value}>
useContext-value-
<Child1 />-<Child2 />
</MyProvider>
</div>
);
};
createRoot(document.getElementById("app3")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.4. React 函数组件 useReducer
const { createRoot } = ReactDOM;
const { useReducer } = React;
const App = () => {
const reducer = (state, action) => {
console.log("useReducer", state, action);
switch (action.type) {
case "increment":
return state + 1;
case "decrement":
return state - 1;
default:
return state;
}
};
let initialState = 0;
const [state, dispatch] = useReducer(reducer, initialState);
return (
<p>
useReducer-{state}-
<button onClick={() => dispatch({ type: "increment" })}>
加
</button>
<button onClick={() => dispatch({ type: "decrement" })}>减</button>
</p>
);
};
createRoot(document.getElementById("app4")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.5. React 函数组件 useCallback
const { createRoot } = ReactDOM;
const { useState, useCallback } = React;
const Child = ({ onClick }) => {
return <button onClick={onClick}>useCallback-点击</button>;
};
const App = () => {
const [count, setCount] = useState(0);
const onClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<p>
<span>useCallback-计数器-{count}-</span>
<Child onClick={onClick} />
</p>
);
};
createRoot(document.getElementById("app5")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.6. React 函数组件 useMemo
const { createRoot } = ReactDOM;
const { useState, useMemo } = React;
const CalcFoo = (v) =>
v.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); // 计算耗时操作
const App = () => {
const [count, setCount] = useState(10000);
const resultValue = useMemo(() => CalcFoo(count), [count]); // 依赖 count 变化
return (
<p>
<span>useMemo-千分符-{resultValue}</span>-
<input value={count} onChange={(e) => setCount(e.target.value)} />
</p>
);
};
createRoot(document.getElementById("app6")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.7. React 函数组件 useRef
const { createRoot } = ReactDOM;
const { useRef } = React;
const App = () => {
const myRef = useRef(null);
return (
<p>
useRef-
<input ref={myRef} />-<button onClick={() => alert(myRef.current)}>alert(input)</button>
</p>
);
};
createRoot(document.getElementById("app7")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.8. React 函数组件 forwardRef
const { createRoot } = ReactDOM;
const { forwardRef } = React;
// 高阶函数包装子组件, 用于 ref 传参
const ChildInput = forwardRef((props, ref) => (
<input ref={ref} style={{ height: "20px" }} />
));
const App = () => {
const inputRef = useRef(null);
const onFocus = () => inputRef.current.focus();
return (
<p>
forwardRef-
<ChildInput ref={inputRef} />-<button onClick={onFocus}>聚焦输入框</button>
</p>
);
};
createRoot(document.getElementById("app8")).render(<App />);
}
</script>
<script type="text/babel">
(function () {
// 案例: 1.9. React 函数组件 useImperativeHandle
const { createRoot } = ReactDOM;
const { forwardRef, useImperativeHandle } = React;
// 高阶函数 forwardRef 包装子组件, 用于 ref 传参
const ChildInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
// useImperativeHandle Hook 用于暴露子组件的实例方法
useImperativeHandle(ref, () => ({
...inputRef,
focus: () => {
console.log("暴露了重新的 focus 方法");
inputRef.current.focus();
inputRef.current.style.color = "red";
},
}));
return <input ref={inputRef} />;
});
const App = () => {
const childRef = useRef(null);
const handleClick = () => childRef.current.focus();
return (
<p>
useImperativeHandle-
<ChildInput ref={childRef} />-<button onClick={handleClick}>聚焦输入框</button>
</p>
);
};
createRoot(document.getElementById("app9")).render(<App />);
})();
</script>
<script type="text/babel">
{
// 案例: 1.10. React 函数组件 useLayoutEffect
const { createRoot } = ReactDOM;
const { useLayoutEffect } = React;
const App = () => {
useLayoutEffect(
() =>
console.log(
"This will run after the browser has completed layout"
),
[]
);
return <p>useLayoutEffect-Hello World</p>;
};
createRoot(document.getElementById("app10")).render(<App />);
}
</script>
<script type="text/babel">
{
// 案例: 1.11. React 函数组件 useDebugValue
const { createRoot } = ReactDOM;
const { useState, useDebugValue } = React;
const useCounter = () => {
const [count, setCount] = useState(0);
console.log(
"在 CDN 模式下 useDebugValue 不会起作用, 只有在开发模式下才会启用"
);
useDebugValue("useCounter", count);
return { count, setCount };
};
const App = () => {
const { count, setCount } = useCounter();
return (
<p>
useDebugValue-count-{count}-
<button onClick={() => setCount(count + 1)}>Increment</button>
</p>
);
};
createRoot(document.getElementById("app11")).render(<App />);
}
</script>
</body>
</html>
2. 案例演示
test-react-api-func.html 资源加载中...