import React, { useState } from 'react';
export default function CounterHook() {
const [count, setCount] = useState(() => 10);
console.log('CounterHook渲染');
function handleBtnClick() {
// 下面这种只会加10
setCount(count + 10);
setCount(count + 10);
setCount(count + 10);
setCount(count + 10);
// 下面这种会加到40
// setCount((prevCount) => prevCount + 10);
// setCount((prevCount) => prevCount + 10);
// setCount((prevCount) => prevCount + 10);
// setCount((prevCount) => prevCount + 10);
}
return (
<div>
<h2>当前计数: {count}</h2>
<button onClick={handleBtnClick}>+10</button>
</div>
);
}
// 父组件
import React, { useEffect, useRef } from 'react';
import Product from './product';
export default function App(props) {
const liRef = useRef();
useEffect(() => {
console.log('ref', liRef.current)
})
return (
<>
<Product ref={liRef} />
</>
);
}
// 子组件 - 函数组件
import React from 'react';
import { forwardRef } from 'react';
export default forwardRef((props, ref) => {
const getProdInfo = function (e) {
console.log(e.target.innerText);
};
return (
<ul onClick={getProdInfo}>
<li ref={ref}>商品1</li>
<li>商品2</li>
</ul>
);
});
// 子组件 - class组件
import React, { forwardRef } from 'react';
class Product extends React.Component {
constructor(props) {
super(props);
}
getProdInfo = function (e) {
console.log(e.target.innerText);
};
render() {
console.log(1, this.props)
return (
<ul onClick={this.getProdInfo}>
<li ref={this.props.innerRef}>商品1</li>
<li>商品2</li>
</ul>
);
}
}
export default forwardRef((props, ref) => <Product innerRef={ref} {...props} />);
联想:
ref的作用:
向父组件暴露一个自定义的 ref 句柄。
默认情况下,组件不会将它们的 DOM 节点暴露给父组件。举例来说,如果你想要 MyInput 的父组件 能访问到 DOM 节点,你必须选择使用 forwardRef。
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />;
});
在上方的代码中,MyInput 的 ref 会接收到 DOM 节点。然而,你可以选择暴露一个自定义的值。为了修改被暴露的句柄,在你的顶层组件调用 useImperativeHandle。
// tools.js
import React, { useState } from 'react';
export function getProdInfo() {
const [price, setPrice] = useState(0);
return price;
}
// App.jsx
import { getProdInfo } from './tools';
export default function App(props) {
getProdInfo(); // 可以使用
const getData = () => {
getProdInfo(); // 报错,因为在普通函数里调用
}
return (
<>
<div onClick={getData}>点我</div>
</>
);
}
有关React自定义hooks
虽然React官方建议自定义hook的名称以"use"开头,但实际上您可以使用任何名称来定义自定义hook。但是,使用"use"开头的命名约定可以帮助其他开发人员更容易地识别它们是React钩子,并且可以帮助您更轻松地遵循React的最佳实践。因此,建议您在自定义hook的名称中使用"use"前缀。
react.FC
react.FC 是 React 中的一个类型定义,用于表示函数组件(Function Components)的类型。在 React 16.8 之后,React 引入了钩子(Hooks) API,使得函数组件可以具有状态和生命周期等特性,因此需要一种方式来为函数组件定义类型。
FC 代表的是 “Function Component”,它是一个泛型类型,可以接受一个泛型参数,该参数表示组件的 props。使用 react.FC 可以为函数组件明确定义输入 props 的类型,以提高代码的类型安全性和可读性。例如:
import React from 'react';
interface MyComponentProps {
name: string;
age: number;
}
const MyComponent: React.FC<MyComponentProps> = ({ name, age }) => {
return (
<div>
<p>Name: {name}</p>
<p>Age: {age}</p>
</div>
);
};
export default MyComponent;
在上面的示例中,MyComponent 是一个函数组件,它接受一个 MyComponentProps 类型的 props 参数。使用 React.FC 来定义组件的类型,有助于编辑器和 TypeScript 编译器在使用组件时进行类型检查。
需要注意的是,虽然 react.FC 在一些项目中非常有用,但它并不是强制要求的,你也可以使用其他方式来定义函数组件的类型。不过,它是一个方便的方式,可以帮助你更清晰地定义组件的输入 props 类型。