[TOC] <br/><br/><br/> # <b style="color:#4F4F4F;">简介说明</b> 原文链接: - [React](https://reactjs.org/docs/react-api.html) - [生命周期](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/) - [React Hooks 使用大全](https://mp.weixin.qq.com/s/Qm7BHndYlvsSmNXZqifwcw) - [我们即将和 API 告别](https://mp.weixin.qq.com/s/PlKMxDYiEerfZgciSAPq6w) - [使用TypeScript](https://mp.weixin.qq.com/s/l4sV6nHT7tPsKpLx5bu-6w) - [Batch Update 浅析](https://zhuanlan.zhihu.com/p/28532725) - [React18新特性深入浅出用户体验大师—transition](https://cloud.tencent.com/developer/article/1899839) - [React18新特性重构](https://mp.weixin.qq.com/s/ltyI3gokuDjhcu20mEDYBg) ``` 版本 :React 作用 :Facebook开发用于构建用户界面的 JavaScript 库 ``` <br/> # <b style="color:#4F4F4F;">安装模块</b> <br/> # <span style="color:#619BE4">Widows</span> ***** npm install react <br/> # <span style="color:#619BE4">Linux</span> ***** npm install react <br/> # <span style="color:#619BE4">引入说明</span> ***** 引入说明 <br/> ### 示例内容 <span style="color:red">1. 浏览器</span> ``` <div id="app"></div> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <script src="https://unpkg.com/react@latest/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@latest/umd/react-dom.development.js"></script> <script type="text/babel"> ReactDOM.render( <div> hello </div>, document.querySelector('#app') ) </script> ``` <br/> # <b style="color:#4F4F4F;">react\<React></b> <br/> # <span style="color:#619BE4">*startTransition()</span> ***** 让你把提供的 fallback 里面的更新标记为 transitions ,这个回调中更新的是不紧急的数据 <br/> # <span style="color:#619BE4">*lazy()</span> ***** 用作代码组件分割,不支持服务端渲染,服务端渲染建议使用:[loadable-components](https://github.com/gregberge/loadable-components) <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` // 这个组件是动态加载的 const SomeComponent = React.lazy(() => import('./SomeComponent')); ``` <br/> # <span style="color:#619BE4">*memo()</span> ***** 高阶组件,用于装饰函数式组件,类似类组件中的pureComponent,用于性能优化,它适用于函数组件,但不适用于 class 组件 <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` 第二个参数可以自定义 function MyComponent(props) { /* 使用 props 渲染 */ } function areEqual(prevProps, nextProps) { /* 如果把 nextProps 传入 render 方法的返回结果与 将 prevProps 传入 render 方法的返回结果一致则返回 true, 否则返回 false */ } export default React.memo(MyComponent, areEqual); 与 class 组件中 shouldComponentUpdate() 方法不同的是, 如果 props 相等,areEqual 会返回 true;如果 props 不相等, 则返回 false。这与 shouldComponentUpdate 方法的返回值相反。 ``` <br/> # <span style="color:#619BE4">~~[aba]-*createFactory()~~</span> ***** 创建一个组件对象 <br/> # <span style="color:#619BE4">*createElement()</span> ***** 创建一个组件对象 <br/> ### 参数说明 <b style="color:#808080;">type:</b> * 类型:字符串 * 默认值:无 * 描述:标签类型 * 可选值:[ ] <b style="color:#808080;">props:</b> * 类型:对象 * 默认值:无 * 描述:参数对象 * 可选值:[ ] <b style="color:#808080;">children:</b> * 类型:字符串 * 默认值:无 * 描述:子元素 * 可选值:[ ] <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` <script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script> <script> ReactDOM.render( React.createElement("div", {id: "hello"}, React.createElement("h1", null, "Hello react"), React.createElement("p", null, "Hello react of p") ), document.getElementById("app") ) </script> ``` <span style="color:red;">2. JSX简化</span> ``` <script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <script type="text/babel"> ReactDOM.render( <div> <p>hello app</p> </div>, document.getElementById("app2") ) </script> ``` <br/> # <span style="color:#619BE4">*cloneElement()</span> ***** 以 element 元素为样板克隆并返回新的 React 元素 <br/> ### 参数说明 <b style="color:#808080;">element:</b> * 类型:字符串 * 默认值:无 * 描述:以 element 元素为样板克隆并返回新的 React 元素 * 可选值:[ ] <b style="color:#808080;">props:</b> * 类型:对象 * 默认值:无 * 描述:参数对象 * 可选值:[ ] <b style="color:#808080;">children:</b> * 类型:字符串 * 默认值:无 * 描述:子元素 * 可选值:[ ] <br/> # <span style="color:#619BE4">*createContext()</span> ***** 创建一个Context对象,用做跨组件通信 <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` const Context = React.createContext<string | null>(null); class Button extends React.Component { static contextType = Context; render() { let color = this.context; return ( <div> <button style={{backgroundColor: color ? color : undefined}}> {this.props.children} </button> <Context.Consumer> { (color2) => ( <input readOnly={true} type="text" value={color2 || ""}/> ) } </Context.Consumer> </div> ); } } class Message extends React.Component { render() { return ( <div> <Button>删除</Button> </div> ); } } class MessageList extends React.Component { render() { return ( <Context.Provider value={"blue"}> <Message/> </Context.Provider> ); } } ``` <br/> # <span style="color:#619BE4">*createRef()</span> ***** 创建一个能够通过 ref 属性附加到 React 元素的 ref <br/> ### 示例内容 <span style="color:red;">1. 获取组件实例</span> ``` class TrialRef extends React.PureComponent { getButton() { return "this is a button"; } render() { return ( <div> <button>{this.getButton()}</button> </div> ); } } export default function() { const pokerRef = useRef<TrialRef>(null); useEffect(() => { console.log(pokerRef.current?.getButton()); }, []); return ( <div style={{width: "100%"}}> <TrialRef ref={pokerRef} /> </div> ); } ``` <span style="color:red;">2. 获取原生实例</span> ``` class TrialRef extends React.PureComponent { public btnRef = React.createRef<any>(); componentDidMount() { console.log(this.btnRef); } render() { return ( <div> <button ref={this.btnRef}>按钮</button> </div> ); } } ``` <br/> # <span style="color:#619BE4">*forwardRef()</span> ***** 创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中 <br/> ### 参数说明 <b style="color:#808080;">callback:</b> * 类型:函数 * 默认值:无 * 描述:接收props 和 ref,返回jsx对象 * 可选值:[ ] <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` const Child = forwardRef(function (props, ref) { console.log(ref.current={a:1}) return (<div>child</div>) }) ``` <br/> # <span style="color:#619BE4">*isValidElement()</span> ***** 验证对象是否为 React 元素,返回值为 true 或 false <br/> # <span style="color:#619BE4">*useState()</span> ***** 函数式组件专用,处理状态 <br/> ### 参数说明 <b style="color:#808080;">initstate:</b> * 类型:object | 函数 * 默认值:无 * 描述:初始值或者工厂函数 * 可选值:[ ] <br/> # <span style="color:#619BE4">*useReducer()</span> ***** 函数式组件专用,useState 的替代方案,可以根据返回值进行处理渲染 <br/> ### 参数说明 <b style="color:#808080;">reducer:</b> * 类型:函数 * 默认值:无 * 描述:纯函数,接收state,action 返回state * 可选值:[ ] <b style="color:#808080;">initialArg:</b> * 类型:对象 * 默认值:无 * 描述:初始值 * 可选值:[ ] <b style="color:#808080;">init:</b> * 类型:函数 * 默认值:无 * 描述:选填,初始方法 * 可选值:[ ] <br/> # <span style="color:#619BE4">*useCallback()</span> ***** 函数式组件专用,渲染完成后执行回调函数 <br/> ### 参数说明 <b style="color:#808080;">callback:</b> * 类型:函数 * 默认值:无 * 描述:更新或挂载之前回调的函数 * 可选值:[ ] <b style="color:#808080;">array:</b> * 类型:数组 * 默认值:无 * 描述:依赖于那些状态变化 * 可选值:[ ] <br/> # <span style="color:#619BE4">*useMemo()</span> ***** 在某个依赖项改变时才重新计算 memoized 值 <br/> ### 参数说明 <b style="color:#808080;">callback:</b> * 类型:函数 * 默认值:无 * 描述:更新或挂载之前回调的函数 * 可选值:[ ] <b style="color:#808080;">array:</b> * 类型:数组 * 默认值:无 * 描述:依赖于那些状态变化 * 可选值:[ ] <br/> # <span style="color:#619BE4">*useEffect()</span> ***** 函数式组件专用,组件[ 挂载或更新之后 ]的hook,可以返回一个函数,在被卸载时执行,与 componentDidMount、componentDidUpdate 不同的是,在浏览器完成布局与绘制之后,传给 useEffect 的函数会延迟调用 <br/> ### 参数说明 <b style="color:#808080;">callback:</b> * 类型:函数 * 默认值:无 * 描述:更新或挂载回调的函数 * 可选值:[ ] <b style="color:#808080;">array:</b> * 类型:数组 * 默认值:无 * 描述:依赖于那些状态变化 * 可选值:[ ] <br/> # <span style="color:#619BE4">*useLayoutEffect()</span> ***** 与 componentDidMount、componentDidUpdate 的调用阶段是一样的 <br/> # <span style="color:#619BE4">*useInsertionEffect()</span> ***** 该签名与 useEffect 相同,但它在所有 DOM 突变 之前 同步触发 <br/> # <span style="color:#619BE4">*useRef()</span> ***** 函数式组件专用,创建可操作dom <br/> ### 参数说明 <b style="color:#808080;">defaultVal:</b> * 类型:字符串 * 默认值:无 * 描述:初始值,记录真实dom,或记录上一次信息 * 可选值:[ ] <br/> # <span style="color:#619BE4">*useImperativeHandle()</span> ***** 让你在使用 ref 时自定义方法暴露给父组件的实例值 <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} ... />; } FancyInput = forwardRef(FancyInput); ``` <br/> # <span style="color:#619BE4">*useContext()</span> ***** 接收一个context对象,用于上下文共享状态 <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` const themes = { light: { foreground: "#000000", background: "#eeeeee" }, dark: { foreground: "#ffffff", background: "#222222" } }; const ThemeContext = React.createContext(themes.light); function App() { return ( <ThemeContext.Provider value={themes.dark}> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar(props) { return ( <div> <ThemedButton /> </div> ); } function ThemedButton() { const theme = useContext(ThemeContext); return ( <button style={{ background: theme.background, color: theme.foreground }}> I am styled by theme context! </button> ); } ``` <br/> # <span style="color:#619BE4">*useTransition()</span> ***** 返回转换的挂起状态的有状态值,以及启动它的函数 <br/> # <span style="color:#619BE4">*useDeferredValue()</span> ***** 接受一个值并返回该值的新副本,该副本将推迟到更紧急的更新 <br/> # <span style="color:#619BE4">*useId()</span> ***** 用于生成在服务器和客户端之间稳定的唯一 ID,同时避免注水不匹配 <br/> # <span style="color:#619BE4">*useSyncExternalStore()</span> ***** 推荐用于从外部数据源读取和订阅的钩子 <br/> # <span style="color:#619BE4">*useDebugValue()</span> ***** 用于在 React 开发者工具中显示自定义 hook 的标签 <br/> # <b style="color:#4F4F4F;">React.Children</b> <br/> # <span style="color:#619BE4">*map()</span> ***** 在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` React.Children.map(children, function[(thisArg)]) ``` <br/> # <span style="color:#619BE4">*forEach()</span> ***** 与 React.Children.map() 类似,但它不会返回一个数组 <br/> # <span style="color:#619BE4">*count()</span> ***** 返回 children 中的组件总数量,等同于通过 map 或 forEach 调用回调函数的次数 <br/> # <span style="color:#619BE4">*only()</span> ***** 验证 children 是否只有一个子节点(一个 React 元素),如果有则返回它,否则此方法会抛出错误。 <br/> # <span style="color:#619BE4">*toArray()</span> ***** 将 children 这个复杂的数据结构以数组的方式扁平展开并返回,并为每个子节点分配一个 key <br/> # <b style="color:#4F4F4F;">React.PureComponent</b> <br/> # <b style="color:#4F4F4F;">React.Component</b> <br/> # <span style="color:#619BE4">constructor()</span> ***** 挂载阶段,构造函数 <br/> ### 参数说明 <b style="color:#808080;">props:</b> * 类型:对象 * 默认值:无 * 描述:父组件传递数据 * 可选值:[ ] <br/> ### 示例内容 <span style="color:red">1. BUS模式思想</span> ``` import axios form 'axios'; import { Spin } from 'antd'; class Loading { constructor () { this.loadingTag = 0; this.subscriptions = []; } add () { this.loadingTag++; this.subscriptions.forEach(f => f(this.loadingTag)); } sub () { this.loadingTag--; this.subscriptions.forEach(f => f(this.loadingTag)); } get () { return this.loadingTag; } subscribe (f) { this.subscriptions.push(f); } } let loadingPublisher = new Loading(); // 对请求进行拦截, 请求之前加一,成功后减一 axios.interceptors.request.use( res => { // 可以添加参数控制是否需要loading状态 if (res && !res.ignoreLoading) { loadingPublisher.add(); } return res; }, error => { return Promise.reject(error); } ); axios.interceptors.response.use( response => { // 可以添加参数控制是否需要loading状态 if (response && response.config && !response.config.ignoreLoading) { loadingPublisher.sub(); } else { return response; } }, error => { loadingPublisher.sub(); return Promise.reject(error.response); // 返回接口返回的错误信息 } ); //实现loading组件 class YMLoading extends Component { constructor (props) { super(props); this.state = { globalLoading: false }; } componentDidMount () { // 增加订阅loading状态更新 loadingPublisher.subscribe((loadingTag)=>{ if (this.state.globalLoading !== !!loadingTag) { this.setState({globalLoading: !!loadingTag}); } }); } render () { return <Spin spinning={this.state.globalLoading} tip= '加载中...' indicator={<img className='loading_spin' src={require('@imgs/loading.png')}/>}/>; } } class App extends Component { render () { return <YMLoading /> } } ``` <span style="color:red">2. 事件完全渲染</span> ``` e.persist() 如果在react中想异步访问事件属性(如在setTimeout内),应该在是处理事件时调用 event.persist(),这会从事件池中移除该合成函数并允许对该合成事件的引用被保留下来 ``` <br/> # <span style="color:#619BE4">dangerouslySetInnerHTML</span> ***** 接收一个对象{__html:html},传入的字符串不进行解析 <br/> # <span style="color:#619BE4">refs</span> ***** 给组件或者标签设置ref属性时,可以坐在refs中获取,已经被弃用通过createRef()传递实例 <br/> ### 示例内容 <span style="color:red">1. 举例说明</span> ``` class TrialRef extends React.PureComponent { getButton() { return "this is a button"; } componentDidMount() { // eslint-disable-next-line react/no-string-refs console.log(this.refs); } render() { return ( <div> {/* eslint-disable-next-line react/no-string-refs */} <button ref={"btn"}>{this.getButton()}</button> {/* eslint-disable-next-line react/no-string-refs */} <input ref={"inp"} type="text" /> </div> ); } } ``` <br/> # <span style="color:#619BE4">context</span> ***** 获取传入的上下文对象,用于状态共享 <br/> # <span style="color:#619BE4">state</span> ***** 状态属性 <br/> # <span style="color:#619BE4">props</span> ***** 父组件传递的数据 <br/> # <span style="color:#619BE4">*defaultProps</span> ***** 可以为 Class 组件添加默认 props <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` class CustomButton extends React.Component { // ... } CustomButton.defaultProps = { color: 'blue' }; ``` <br/> # <span style="color:#619BE4">setState()</span> ***** 触发状态更新 <br/> ### 参数说明 <b style="color:#808080;">updater:</b> * 类型:对象 * 默认值:无 * 描述:更新的内容 * 可选值:[ ] <b style="color:#808080;">callback:</b> * 类型:函数 * 默认值:无 * 描述:更新后的回调函数函数 * 可选值:[ ] <br/> # <span style="color:#619BE4">forceUpdate()</span> ***** 强制更新,跳过shouldComponentUpdate() <br/> # <span style="color:#619BE4">~~[aba]-componentWillMount()~~</span> ***** 挂载阶段 <br/> # <span style="color:#619BE4">~~[aba]-getChildContext()~~</span> ***** 提供context给子孙组件 <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` import React from 'react'; import propTypes from "prop-types"; import './App.css'; class Button extends React.Component { static contextTypes = {color: propTypes.string}; render() { return ( <button style={{backgroundColor: this.context.color}}> {this.props.children} </button> ); } } class Message extends React.Component { render() { return ( <div> <Button>删除</Button> </div> ); } } class MessageList extends React.Component { static childContextTypes = {color: propTypes.string}; getChildContext() { return {color: "blue"}; } render() { return ( <Message/> ); } } ``` <br/> # <span style="color:#619BE4">*getDerivedStateFromProps()</span> ***** 替代componentWillMount和componentWillReceiveProps <br/> ### 参数说明 <b style="color:#808080;">props:</b> * 类型:对象 * 默认值:无 * 描述:父组件传递数据 * 可选值:[ ] <b style="color:#808080;">stateops:</b> * 类型:对象 * 默认值:无 * 描述:状态数据 * 可选值:[ ] <br/> # <span style="color:#619BE4">render()</span> ***** 渲染组件 <br/> ### 示例内容 <span style="color:red;">1. 生命周期</span> ``` import 'antd/dist/antd.css' import React, {useState} from 'react'; import ReactDOM from 'react-dom'; import {Form, Input, Button} from 'antd'; class HorizontalLoginForm extends React.Component { static getDerivedStateFromProps(props, state){ console.log("getDerivedStateFromProps"); return props; } getSnapshotBeforeUpdate(prevProps, prevState) { console.log("getSnapshotBeforeUpdate"); return prevProps; } shouldComponentUpdate(nextProps, nextState, nextContext) { console.log("shouldComponentUpdate"); return true; } render() { console.log("render"); return ( <Form layout="inline"> <Form.Item> <Input/> </Form.Item> <Form.Item> <Input/> </Form.Item> <Form.Item> <Button type="primary">Log in</Button> </Form.Item> </Form> ); } componentDidUpdate(prevProps, prevState, snapshot) { console.log("componentDidUpdate"); } componentDidMount() { console.log("componentDidMount"); } componentWillUnmount() { console.log("componentWillUnmount") } } function Parent() { let [val, setVal] = useState(null); return ( <> <HorizontalLoginForm val={val}/> <button onClick={() => { setVal(Date.now()); }}>UPDATE </button> </> ) } ReactDOM.render(<Parent/>, document.getElementById("root")); ``` <br/> # <span style="color:#619BE4">componentDidMount()</span> ***** 挂载阶段 <br/> # <span style="color:#619BE4">~~[aba]-componentWillReceiveProps()~~</span> ***** 父组件更新阶段 <br/> # <span style="color:#619BE4">shouldComponentUpdate()</span> ***** 组件更新阶段,该函数会返回一个布尔值,决定了后续是否执行 render,首次渲染不会调用该函数 <br/> ### 参数说明 <b style="color:#808080;">nextProps:</b> * 类型:对象 * 默认值:无 * 描述:父组件传递数据 * 可选值:[ ] <b style="color:#808080;">nextState:</b> * 类型:对象 * 默认值:无 * 描述:状态数据 * 可选值:[ ] <br/> ### 示例内容 <span style="color:red;">1. 减少重复渲染</span> ``` shouldComponentUpdate(nextProps, nextState) { return nextState.someData !== this.state.someData } ``` <br/> # <span style="color:#619BE4">~~[aba]-componentWillUpdate()~~</span> ***** 组件状态将更新阶段 <br/> # <span style="color:#619BE4">getSnapshotBeforeUpdate()</span> ***** 组件更新阶段,render之后,componentWillUpdate之前,该方法返回内容会传递给componentDidUpdate方法第三个参数中 <br/> ### 参数说明 <b style="color:#808080;">prevProps:</b> * 类型:对象 * 默认值:无 * 描述:父组件传递数据 * 可选值:[ ] <b style="color:#808080;">prevState:</b> * 类型:对象 * 默认值:无 * 描述:状态数据 * 可选值:[ ] <br/> # <span style="color:#619BE4">componentDidUpdate()</span> ***** 组件状态更新完毕阶段 <br/> ### 参数说明 <b style="color:#808080;">prevProps:</b> * 类型:对象 * 默认值:无 * 描述:父组件传递数据 * 可选值:[ ] <b style="color:#808080;">prevState:</b> * 类型:对象 * 默认值:无 * 描述:状态数据 * 可选值:[ ] <b style="color:#808080;">prevInfo:</b> * 类型:对象 * 默认值:无 * 描述:getSnapshotBeforeUpdate返回内容 * 可选值:[ ] <br/> # <span style="color:#619BE4">componentWillUnmount()</span> ***** 组件卸载阶段 <br/> # <span style="color:#619BE4">*getDerivedStateFromError()</span> ***** 错误处理,父组件捕获子组件错误 <br/> # <span style="color:#619BE4">componentDidCatch()</span> ***** 错误处理 <br/> ### 参数说明 <b style="color:#808080;">error:</b> * 类型:对象 * 默认值:无 * 描述: * 可选值:[ ] <b style="color:#808080;">info:</b> * 类型:对象 * 默认值:无 * 描述: * 可选值:[ ] <br/> # <b style="color:#4F4F4F;">React.StrictMode</b> <br/> # <span style="color:#619BE4">[com]-StrictMode()</span> ***** 不会渲染任何真实的UI。它为其后代元素触发额外的检查和警告,同时组件中render方法会渲染两次,为了避免副作用的影响产生的BUG行为,这个行为只会在开发模式存在 <br/> # <b style="color:#4F4F4F;">React.Fragment</b> <br/> # <span style="color:#619BE4">[com]-Fragment()</span> ***** 组件能够在不额外创建 DOM 元素的情况下,让 render() 方法中返回多个元素,你也可以使用其简写语法 <></> <br/> # <b style="color:#4F4F4F;">React.SuspenseList</b> <br/> # <span style="color:#619BE4">[com]-SuspenseList()</span> ***** 用于包裹异步加载的组件,提供fallback属性,用于无法加载时的显示 <br/> # <b style="color:#4F4F4F;">React.Suspense</b> <br/> # <span style="color:#619BE4">[com]-Suspense()</span> ***** 用于包裹异步加载的组件,提供fallback属性,用于无法加载时的显示 <br/> ### 示例内容 <span style="color:red;">1. 举例说明</span> ``` // 该组件是动态加载的 const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( // 显示 <Spinner> 组件直至 OtherComponent 加载完成 <React.Suspense fallback={<Spinner />}> <div> <OtherComponent /> </div> </React.Suspense> ); } ``` <br/> # <b style="color:#4F4F4F;">React.Profiler</b> <br/> # <span style="color:#619BE4">[com]-Profiler()</span> ***** react组件渲染分析器组件 <br/>