博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
001.React的记录
阅读量:6548 次
发布时间:2019-06-24

本文共 29894 字,大约阅读时间需要 99 分钟。

React-demo

react-demo: https://github.com/Zjingwen/react-demo欢迎git clone复制代码

React的方法

生命周期详解

constructor 实例化

class A extends React.Component{	constructor(){		super();	}}复制代码
  • 实例化对象
  • 继承React.Component
  • 初始化state

static getDerivedStateFromProps

class A extends React.Component{	static getDerivedStateFromProps(props,state){		return Object	}}复制代码
  • update更新时,render之前,dom渲染前
  • 必须有初始化state
  • 静态方法,没有this
  • 可以return出对象,设置state
class Count extends Component{  constructor(props){    super(props);    this.state = {      count: 0,    }  };  static getDerivedStateFromProps(props){    return {count: props.count*2};  };  render(){    return (      

Count-Child-state: {this.state.count}

Count-Child-props: {this.props.count}

) }};class Time extends Component{ constructor(props){ super(props); this.state={ time: this.props.time, } }; static getDerivedStateFromProps(props,state){ console.log(state); return null; }; handleClick(){ this.setState({ time: new Date().toString() }); } render(){ const {time} = this.state; return(
this.handleClick()}/>

{time}

) };};function GetDerivedStateFromPropsComponent (){ const [count,setCount] = useState(0); const [time] = useState(new Date().toString()); return (
setCount(s=>s+1)}/>
)};复制代码

shouldComponentUpdate

class A extends React.Component{	shouldComponentUpdate(nextProps, nextState){		return Boolean	}}复制代码
  • update更新时,render之前,dom渲染前
  • return 一个布尔值来判断是否渲染
  • 默认return true
class Time extends Component{  shouldComponentUpdate(nextPorps){    if(this.props.time !== nextPorps.time){      // 保证每次time不同时更新      console.group('shouldComponent-props');      console.log(nextPorps);      console.log(this.props);      console.groupEnd();      return true;    }    return false;  };    render(){    return(      
{this.props.time}
) }};function ShuldComponentUpdateComponent() { const [time,setTime] = useState(new Date().toString()); return(
setTime(new Date().toString())} />
)};复制代码

render

class A extends React.Component{	render(){		return JSX	}}复制代码
  • 将jsx渲染为真实DOM

getShapshotBeforeUpdate

class A extends React.Component{	getShapshotBeforeUpdate(prevProps,prevState){		return ‘getShapshotBeforeUpdate’	}	componentDidUpdate(prevProps,prevState,snapshot){	   // TODO snapshot == ‘getShapshotBeforeUpdate’	}}复制代码
  • update更新时,render之前,dom渲染前
  • 无默认返回值,可返回null
  • return 一个值,用来作为componentDidUpdate的第三个参数
class Child extends Component {  constructor(props) {    super(props);    this.state = {      ...props,    };  }  getSnapshotBeforeUpdate(prevProps, prevState) {    console.group('getSnapshotBeforeUpdate');    console.log(prevProps);    console.log(prevState);    console.groupEnd();    if (prevProps.time !== prevState.time) {      this.setState({        time: prevProps.time,      });    }    return 'getSnapshotBeforeUpdate';  }  componentDidUpdate(prevProps, prevState, snapshot) {    console.group('componentDidUpdate');    console.log(prevProps);    console.log(prevState);    console.log(snapshot);    console.groupEnd();  }  render() {    return (      

{this.state.time}

); }}function GetShapshotBeforeUpdateComponent() { const [time, setTime] = useState(new Date().toString()); return (
setTime(new Date().toString())} />
);}复制代码

componentDidMount

class A extends React.Component{	componentDidMount(){}}复制代码
  • render之后,dom渲染后
  • 唯一的会在服务端渲染调起的生命周期钩子函数。
class Time extends Component {  componentDidMount() {    console.log('ComponentDidMount');  }  render() {    return (      

{new Date().toString()}

); }}function ComponentDidMountComponent() { const [show, setShow] = useState(false); return (
setShow(!show)} /> { show &&
}
);}复制代码

componentDidUpdate

class A extends React.Component{	componentDidUpdate(prevProps,prevState,snapshot){}}复制代码
  • update更新时,render之后,dom渲染后
  • snapshot为getShapshotBeforeUpdate的return
参照getShapshotBeforeUpdate的code demo复制代码

componentWillUnmount

class A extends React.Component{	componentWillUnmount(){}}复制代码
  • dom卸载
class Time extends Component {  componentWillUnmount() {    console.log('componentWillUnmount');  }  render() {    return (      

{new Date().toString()}

); };}function ComponentWillUnmountComponent() { const [show, setShow] = useState(true); return (
setShow(!show)} /> {show &&
}
);}复制代码

componentDidCatch

class A extends React.Component{    componentDidCatch(error,errorInfo){}}复制代码
  • 只有在render中报错才会被捕获
  • 为什么不用try/catch:try/catch更加适合命令式代码,而componentDidCatch会捕获组件树中的报错
class ErrorBoundary extends Component {  constructor(props) {    super(props);    this.state={      error: false,      errorInfo: null,    };  }  componentDidCatch(error, errorInfo) {    console.log(errorInfo.componentStack);    this.setState({      error: error.toString(),      errorInfo: errorInfo.componentStack,    });  }  render() {    if (this.state.error) {      return (        

error: {this.state.error}

errorInfo:{this.state.errorInfo}

); } return this.props.children; }};ErrorBoundary.propTypes = { children: PropTypes.node.isRequired,};class Input extends Component { constructor() { super(); this.state= { throw: false, }; } handleClick() { this.setState((s)=>({ throw: !s.throws, })); } render() { if (this.state.throw) throw new Error('I throw'); return this.handleClick()} />; }};function ComponentDidCatchComponent() { return (
);};复制代码

触发流程

初始化

constructor()static getDerivedStateFromProps(props,state)render()componentDidMount()复制代码
class Flow extends React.Component{  constructor(){    super();    this.state = {};    console.group('初始化阶段');    console.log('constructor');  };  static getDerivedStateFromProps(){    console.log('getDerivedStateFromProps');    return null;  };  componentDidMount(){    console.log('componentDidMount');    console.groupEnd();  }    render(){    console.log('render');    return (      

constructor

|
static getDerivedStateFromProps()
|
render
|
componentDidMount

) };}function MountingComponent (){ const [show,setShow] = useState(false); return (
setShow(!show)}/> {show &&
}
)};复制代码

属性更新

New Props

static getDerivedStateFromProps(props,state)shouldComponentUpdate(nextProps, nextState)render()getSnapshotBeforeUpdate(prevProps,prevState)componentDidUpdate()复制代码
class Flow extends React.Component{  state = {};  static getDerivedStateFromProps(){    console.group('触发传递新的props');    console.log('getDevivedStateFromProps');    return null;  };  shouldComponentUpdate(){    console.log('shouldComponentUpdate');    return true;  };  getSnapshotBeforeUpdate(){    console.log('getSnapshotBeforeUpdate');    return null;  };  componentDidUpdate(){    console.log('componentDidUpdate');    console.groupEnd();  };  render(){    console.log('render');    return(      

{this.props.title}

static getDevivedStateFromPorps

|
shouldComponentUpdate
|
getSnapshotBeforeUpdate
|
componentDidUpdate

) }};function NewpropsComponent(){ const [time,setTime] = useState(new Date().toString()); return (
setTime(new Date().toString())}/>
)};export default NewpropsComponent;复制代码

setState()

static getDerivedStateFromProps()shouldComponentUpdate()render()getSnapshotBeforeUpdate()componentDidUpdate()复制代码
class SetStateComponent extends React.Component{  state = {    time: new Date().toString(),  };    static getDerivedStateFromProps(){    console.group('设置属性');    console.log('getDerivedStateFromProps');    return null;  };  shouldComponentUpdate(){    console.log('shouldComponentUpdate')    return true;  };  getSnapshotBeforeUpdate(){    console.log('getSnapshotBeforeUpdate');    return null;  };  componentDidUpdate(){    console.log('componentDidUpdate');    console.groupEnd();  };  handleClick(){    this.setState({      time: new Date().toString()    });  }  render(){    console.log('render');    return (      
this.handleClick()} />

{this.state.time}

static getDerivedStateFromProps
|
shouldComponentUpdate
|
render
|
getSnapshotBeforeUpdate
|
componentDidUpdate
) }}复制代码

forceUpdate()

getDerivedStateFromProps()render()getShapshotBeforeUpdate()componentDidUpdate()复制代码
class ForceUpdateComponent extends React.Component{  state = {};  static getDerivedStateFromProps(){    console.group('forecUpdate更新');    console.log('getDerivedStateFromProps');    return true;  };  getSnapshotBeforeUpdate(){    console.log('getShapshotBeforeUpdate');    return null;  };  componentDidUpdate(){    console.log('componentDidUpdate');    console.groupEnd();  }  render(){    console.log('render')    return(      
this.forceUpdate()} />
static getDerivedStateFromProps
|
getShapshotBeforeUpdate
|
componentDidUpdate
) }}复制代码

触发生命周期的api

setState 设置状态

setState((State)=>({object}),function callback])复制代码
// 完全写法this.setState(State=>({    ...State}),()=>{    ...})// 简单写法this.setState({    ...})复制代码
  • 触发一轮生命周期getDerivedStateFromProps->shouldComponentUpdate->render->getSnapshotBeforeUpdate->componentDidUpdate
  • prevState为当前组件的state值
  • callback,为状态设置之后,state经过所有生命周期后调用

forceUpage 强制更新

forceUpage(function callback)复制代码
this.forceUpage(()=>{    ...})复制代码
  • 触发一轮生命周期getDerivedStateFromProps->render->componentDidUpdate
  • callback,为生命周期之后调用

React.Component

  • react的抽象基础类
class A extends React.Component{}复制代码

React.PureComponent

  • 内置一个浅比较,比较props和state,决定是否render,用于提高性能
  • 只是进行浅对比,无法对比复合数据
  • 用于避免无状态组件的重复渲染
class A extends React.PureComponent{}复制代码

React.memo(()=>{},()=>{});

  • 组件仅在它的 props 发生改变的时候进行重新渲染
  • 和React.PureComponent类似功能一直,但这是一个纯函数用法
  • 只是进行浅对比,无法对比复合数据
const A = React.memo((props)=>{    return JSX},(prevProps,nextProps)=>{    return null | false})复制代码
const MemoComponent = React.memo((props)=>{  return (    
{props.time}
);}, (prevProps, nextProps)=>{ if (prevProps.time !== nextProps.time) { return null; } return false;});function Memo() { const [time, setTime] = useState(new Date().toString()); return (
memo
setTime(new Date().toString())} />
);};复制代码

React.createRef()

  • 创建节点引用
  • 通过ref属性附加到React元素
  • 可以通过curent访问到节点
  • ref更新发生在componentDidMount、componentDidUpdate时
  • 无法在函数组件上使用,因为没有实例
class CreateRefComponent extends Component {  constructor() {    super();    this.state = {      el: null,    };    this.ref = React.createRef();  }  componentDidMount() {    this.setState({      el: this.ref.current.innerHTML,    });  }  render() {    return (      
createRef

el: {this.state.el}

); }}复制代码

React.isValidElement(object)

  • 验证对象是否为React元素。返回true或false。
  • 必须传递一个对象
let D = React.createElement('div');React.isValidElement(D);复制代码
function ChildFunction() {  return (    
Child-function
);};class ChildComponent extends Component { render() { return (
Child-Component
); }};function IsValidElementComponent() { const D = React.createElement('div'); return (

createElement: {React.isValidElement(D).toString()}

Function Component: {React.isValidElement(ChildFunction()).toString()}

class Component: {React.isValidElement(

).toString()}

);};复制代码

React.Children

  • 遍历children,返回数组
array React.Children.map(children,function callback) 复制代码
class Map extends Component {  render() {    const arr = React.Children.map(this.props.children, (v)=> v);    return (      
{arr}
); }};Map.propTypes = { children: PropTypes.node.isRequired,};function Index() { return (

A

B

C

D

E

F

);};复制代码
  • 遍历children,无返回
void React.Children.forEach(children,function callback) 复制代码
class ForEact extends Component {  render() {    const arr = [];    React.Children.forEach(this.props.children, (v) => arr.push(v));    return (      
{arr}
); }};ForEact.propTypes = { children: PropTypes.node.isRequired,};function Index() { return (

A

B

C

D

E

F

);};复制代码
  • 返回children的长度
number React.Children.count(children) 复制代码
class Count extends Component {  render() {    const count = React.Children.count(this.props.children, (v)=> v);    return (      
{count}
); }};Count.propTypes = { children: PropTypes.node.isRequired,};function Index() { return (

A

B

C

D

E

F

);};复制代码
  • 判断children是否为1,不为1报错
void React.Children.only(children) 复制代码
class Only extends Component {  render() {    const {title} = this.props;    let e = null;    let o = null;    try {      o = React.Children.only(this.props.children);    } catch (error) {      e = error;    };    return (      
{e && Object.keys(e).map((v) => e[v])} {o}
); }};Only.propTypes = { children: PropTypes.node.isRequired, title: PropTypes.string.isRequired,};function Index() { return (

A

B

C

D

E

F

A

);};复制代码
  • 把children,从对象转换为数组
array React.Children.toArray(children,function callback)复制代码
class ToArray extends Component {  render() {    const arr = React.Children.toArray(this.props.children);    return (      

isArray: {Array.isArray(arr).toString()}

{arr}
); }};ToArray.propTypes = { children: PropTypes.node.isRequired,};function Index() { return (

A

B

C

D

E

F

);};复制代码

React.Fragment

  • 允许创建一对React.Fragment的元素,这样就不用额外创建用于包裹的元素
// 完全写法render(){    return(        
hello React
)}// 缩略写法render(){ return( <> hello React )}复制代码

React.createElement

  • 创建react对象
React.createElement(  type,  [props],  [...children]);复制代码
class Hello extends React.Component {  render() {    return React.createElement('div', null, `Hello ${this.props.toWhat}`);  }}ReactDOM.render(  React.createElement(Hello, {toWhat: 'World'}, null),  document.getElementById('root'));复制代码

React.createFactory

  • 返回一个React元素的函数。
React.createFactory({  type,  [props],  [...children]})复制代码
function createFactory() {  const li = React.createFactory('li');  const Child1 = li(null, 'child-1');  const Child2 = li(null, 'child-2');  const Root = React.createElement('ul', '', Child1, Child2);  return (    
{Root}
);}复制代码

React.cloneElement

  • 克隆并返回一个新的React元素
React.cloneElement({    type,    [props],    [...children]})复制代码
class C extends React.Component {  render(){    var D = React.createElement('div');    return React.cloneElement(      D,      null,      'hello React'    );  }}复制代码

React.forwordRef(props,ref)

TODO @jingwen 需要独立文章分析

  • 引用转发ref给组件
React.forwordRef(props,ref)复制代码
// 简单用法function Input(props) {  const {forwardRef} = props;  return (      );};Input.propTypes = {  forwardRef: propTypes.object,};Input.defaultProps={  forwardRef: {},};class ForwardRefComponent extends Component {  constructor() {    super();    this.state = {      refs: React.createRef(),    };  }  handleFocus() {    const {refs: {current}} = this.state;    current.focus();  }  render() {    const {refs} = this.state;    const FancyInput = React.forwardRef((props, ref)=>{      return ;    });    return (      
this.handleFocus()} />
); }}复制代码
// 转发ref给后代function wrapped(Component) {  class Wrapped extends React.Component {    render() {      const {forwardedRef, ...props} = this.props;      return 
; } } return React.forwardRef((props, ref) => { return
; });}class Input extends React.Component { constructor(props) { super(props); this.ref = React.createRef(); }; handleFocus() { const {current} = this.ref; current.focus(); } render() { const props = this.props; return ( ); }}class Hoc extends React.Component { constructor() { super(); this.state = { refs: React.createRef(), }; }; handleFocus() { const {refs: {current}} = this.state; current.handleFocus(); } render() { const {refs} = this.state; const InputHoc = wrapped(Input); return (
this.handleFocus()} />
); }};复制代码

React.lazy or React.Suspense

  • React.lazy,动态导入组件
  • React.Suspense,等待导入时的显示
const TimeFun = lazy(()=> import('./TimeFun'));const TimeClass = lazy(()=> import('./TimeClass'));class Index extends Component {  render() {    const Time = new Date().toString();    return (      
Loading...}>

parent: {Time}

); }}复制代码
class TimeClass extends React.Component {  render() {    const Time = new Date().toString();    return 
lazy-time-class: {Time}
; };};export default TimeClass;复制代码
function TimeFun() {  const Time = new Date().toString();  return (
lazy-time-fun: {Time}
);};export default TimeFun;复制代码

React.StrictMode

  • 给组件的任何部分开启严格模式
  • 识别具有不安全生命周期的组件
  • 关于遗留字符串ref API使用的警告
  • 关于已弃用的findDOMNode用法的警告
  • 检测意外的副作用
  • 检测遗留上下文API
class Index extends Component {  render() {    return (      
StrictMode
); }};复制代码

Context

  • 组件设置全局参数
  • createContext,设置context的默认值
const A = React.createContext('aaaa');复制代码
  • Context.Provider,允许组件订阅该context的参数
  • Class.contextType,设置当前组件订阅的context。当找不到Provider的时候使用。context值可以在componentDidMount、componentUpdate、componentWillUnmount、render中获取
// 两种设置形式const context = React.createContext('aaa');class A extend React.Component{    static contextType = context;}class B extend React.Component{}B.contextType = context;复制代码
  • Context.Consumer,
// 简单例子const ThemeContext = React.createContext('light');class ThemedButton extends React.Component {  static contextType = ThemeContext;  render() {    return ;  }}function Toolbar(props) {  return (    
);}class Index extends Component { render() { return (
); }}复制代码
  • Consumer,设置多个上下文
const themes = {  light: {    background: '#eeeeee',  },  dark: {    background: '#222222',  },};const ThemeContext = createContext(  themes.light,);class ThemeButton extends Component {  static contextType = ThemeContext;  render() {    const props = this.props;    const theme = this.context;    return (          );  }};class Index extends Component {  constructor(props) {    super(props);    this.state = {      theme: themes.light,    };  }  handleTheme() {    this.setState((state)=>({      theme: JSON.stringify(state.theme) === JSON.stringify(themes.dark)        ? themes.light        : themes.dark,    }));  };  render() {    return (      
this.handleTheme()}> Change Theme
); }}复制代码

ReactDOM.createPortal

ReactDOM.createPortal(    React.Component | JSX, // react组件    element,// 节点元素);复制代码

defaultProps

  • 设置props的默认值
class A extends React.Component{    constructor(props){        super(props);        console.log(props)    };        // 集成写法    static defaultProps = {        test: 'test',            };}// 外置写法A.defaultPorps = {    test: 'test',}复制代码

PropTypes

TODO复制代码

Render Props

  • 解决组件交叉使用问题
function Cat(props) {  const STYLE = {    width: 20,    height: 20,    background: '#FF00FF',    position: 'absolute',    left: props.mouse.x,    top: props.mouse.y,  };  return (    
);}Cat.propTypes = { mouse: propTypes.object.isRequired,};class Mouse extends Component { constructor(props) { super(props); this.state={ x: 0, y: 0, }; } handleMove(event) { this.setState({ x: event.clientX, y: event.clientY, }); }; render() { const STYLE = { width: 500, height: 500, background: '#eee', display: 'inline-block', }; return (
this.handleMove(e)}> {this.props.render(this.state)}
); }}Mouse.propTypes = { render: propTypes.func.isRequired,};class Index extends Component { render() { return (
(
)} />
); }};复制代码

React的事件池

TODO复制代码

Hooks

useState 状态钩

  • 用来设置和更新状态
const [状态变量,更新函数] = useState(默认值)复制代码
function A(){  const [count, setCount] = useState(0);  return(    

Count: {count}

)};复制代码

useEffect(function,[]) 效果钩

useEffect(()=>{    // componentDidMount    // componentDidUpdate    return ()=>{        // componentWillUnmount    }},[]);复制代码
  • useEffect是componentDidMount、componentDidUpdate、componentWillUnmount的结合。
  • 默认情况下,useEffect,会在每次componentDidMount、componentDidUpdate时执行。
  • 可以拿到DOM结构
function A(){  const [count,setCount] = useState(0)  useEffect(()=>{    document.getElementById('useEffect-A-count').innerText = `count: ${count}`;  });  function handleClick(){    setCount(count+1);  };  return (    

)};复制代码
  • 如何在组件compoenntWillUnmount时触发useEffect
function B(){  const [show,setShow] = useState(true);  function Child(){    useEffect(()=>{      console.log('componentDidMount');      return ()=>{        console.log('componentWillUnmount');      }    })    return 

B-Child

}; return (

请查看log

setShow(!show)}/> {show &&
}
)};复制代码
  • 利用第二个参数,让useEffect不会过度渲染
  • 为空数组,表示不依赖props或者state,将不会更新
  • 数组内表示当新的赋值,如果新值和旧值不想等,就更新
function D(){  const [count,setCount] = useState(0);  const [double,setDouble] = useState(count*2);  const [three,setThree] = useState(count*3);    useEffect(()=>{    setDouble(count*2);  },[count*2])  useEffect(()=>{    setThree(count);  },[])// 为空数组,表示不依赖props或者state,将不会更新  return (    

+1: {count}

*2: {double}

not: {three}

setCount(count+1)}/>
)};复制代码

useLayoutEffect(function,[])

  • DOM渲染前反应的钩子
  • 基本配置和useEffect一致
function E(){  const [name,setName] = useState(null);  useLayoutEffect(()=>{    setTimeout(()=>{      setName('useLayoutEffect');    },3000);  },[]);  useEffect(()=>{    setTimeout(()=>{      setName('useEffect');    },3000);  },[]);  return(    
{name}
)}复制代码

useContext(createContext)

  • 参数在所有子组件中都能获取
const CountContext = createContext();function F(){  function ChildA(){    const countChild = useContext(CountContext);    return (      

Child A count: {countChild}

) }; function ChildB(){ const countChild = useContext(CountContext); return (

Child B count: {countChild}

) }; const [count,setCount] = useState(0); return (
setCount(count+1)}/>
)}复制代码

useReducer(reducer,initialState)

  • 类似redux的功能
const [state,dispatch] = useReducer(reducer,initialState,{action});// const [属性,动作] = useReducer(动作函数,初始值属性,初始动作);// 如何触发:dispatch(type);复制代码
function reducer(state,action){  switch(action){    case 'reset':      return 0;      break;    case 'increment':      return state+1;      break;    case 'decrement':      return state-1;      break;    default:      return state;  };};function useReduceComponent(){  const [state,dispatch] = useReducer(reducer,0,'reset');  return (    

{state}

dispatch('increment')}/>
dispatch('decrement')}/>
dispatch('reset')}/>
);};复制代码

useCallback(()=>{},[])

  • 返回一个记忆的memoized,默认情况下会记录上一次传递的值
  • 可以替代shouldComponentUpdate使用
function MemoizedConst ({num}){  const memoizedCallback = useCallback(()=>{    return num;  },[]);  return (    

记忆 num > {memoizedCallback()}

原始 num > {num}

)};function UseCallbackComponent (){ let [num,setNum] = useState([1,2,3]); useEffect(()=>{ setTimeout(function(){ setNum([3,4,5]) },3000); },[]); return (
);};// [1,2,3]// dely 3000ms// [3,4,5]复制代码
  • 保存事件,让组件不会重复创建新方法,当你重复点击时,InputComponentState的handleClick的事件总是由组件新创建的。而InputComponentCallback的handleClick会被记忆下来,不会新创建。有利于提高性能。
let InputComponentStateFunc = null;function InputComponentState(){  const [state,setState] = useState(0);  function handleClick(){    setState(state=> state+1);  };    console.group('InputComponentStateFunc');    console.log(InputComponentStateFunc === handleClick);  console.groupEnd();  InputComponentStateFunc = handleClick;  return (    
)};let InputComponentCallbackFunc = null;function InputComponentCallback(){ const [state,setState] = useState(0); const handleClick = useCallback((event) => { setState(state=> state+1); event.persist(); },[]); console.group('InputComponentCallbackFunc'); console.log(InputComponentCallbackFunc === handleClick); console.groupEnd(); InputComponentCallbackFunc = handleClick; return (
{}
)};function UseCallbackComponent (){ return (
);};复制代码

useMemo(function,[])

  • 和useCallback基本一致,我还没发现有什么区别Q。Q
function MemoizedLet({num}){  const memo = useMemo(()=> num,[]);  return (    

记忆 num > {memo}

原始 num > {num}

)};function MemoizedConst({num}){ const memo = useMemo(()=> num,[num]); return (

记忆 num > {memo}

原始 num > {num}

)};function useMemoComponent(){ const [num,setNum] = useState([1,2,3]); useEffect(()=>{ setTimeout(()=>{ setNum([3,4,5]); },3000); },[]); return (
)};复制代码

useRef()

  • 返回一个ref对象,这个对象将维持在组件的整个生命周期
function useRefComponent(){  const inputEl = useRef(null);    function handleClick(){    inputEl.current.focus();  }  return(    
)};复制代码

useImperativeMethods(ref,()=>({}))

  • 向父组件公开ref实例
  • 只能应用于forwardRef(props,ref)
function FancyInput(props,ref){  const inputRef = useRef(null);  useImperativeMethods(ref,()=>({    focus: ()=>{      inputRef.current.focus();    }  }));  return };const Input = forwardRef(FancyInput);function UseImperativeMethodsComponent(){  const fancyInputRef = useRef(null);  function handleClick(){    fancyInputRef.current.focus();  };  return (    
)};复制代码

useMutationEffect(function,[])

  • 和useEffect、useLayoutEffect类似
  • useMutationEffect会在更新阶段触发
function Effect(){  const [state,setState] = useState('请看log')  useEffect(()=>{    setTimeout(()=>{      console.log('useEffect');    });  },[]);  useLayoutEffect(()=>{    setTimeout(()=>{      console.log('useLayoutEffect');    });  },[]);  useMutationEffect(()=>{    setTimeout(()=>{      console.log('useMutationEffect');    });  },[]);  return (    
{state}
)}function useMutationEffectComponent(){ const [show,setShow] = useState(false); return (
{ show &&
}
setShow(!show)}/>
)};复制代码

HOC 高级组件

解释

  • 一个参数为React组件的函数,并且返回一个新函数,一个类工厂。

优点

  • 高内聚,低耦合
  • 代码复用,高度模块化

基本用途

  • 增删改props
  • 渲染劫持

公式

React.Component function WrappedComponent(React.Component:Component)复制代码

简单例子

function WrappedComponent(Wrapped){  return class extends React.Component{    render(){      const props = {        context: 'React',      }      return 
; } }};class Child extends React.Component{ render(){
return
hello {this.props.context}
};};class App extends React.Component{ render(){ const HOCchild = WrappedComponent(Child); return(

App

) }};复制代码

注意

  • 不要改变原始组件,使用组合的形式
// 错误示范// WrappedComponent 中会覆盖组件的componentDidMount方法// 而且使用者必须要知道被覆盖方法的具体用途,才能避免方法冲突覆盖function WrappedComponent(Wrapped) {  Wrapped.prototype.componentDidMount = ()=>{    console.log('WrappedComponent');  };  return Wrapped;};class Child extends React.Component{  componentDidMount(){    console.log('Child');  }  render(){
return
hello React
};};class App extends React.Component{ render(){ const HOCchild = WrappedComponent(Child); return(
) }};复制代码
// 正确示范function wrappedComponent(Wrapped){    return class React.Component{        componentDibMount(){            console.log('componentDibMount')        }    };};复制代码
  • 不要直接修改HOC的props,最好独立变量
// 错误示范// props中可能包含太多多余的属性,无法确保高阶组件的灵活度和可重用性function WrappedComponent(Wrapped){    return class React.Component{        return 
}}复制代码
// 正确function WrappedComponent(Wrapped){    return class React.Component{        const {detail} = this.props;        return 
}}复制代码
  • 包装显示名称,便于调试
function WrappedComponent(Wrapped){  class WithSubscription extends React.Component{    componentDidMount(){      console.log('WrappedComponent');    }    render(){
return
} }; function getDiplayName(W){ return W.displayName || W.name || 'Component'; } WithSubscription.displayName = `WithSubscription(${getDiplayName(Wrapped)})` return WithSubscription;};复制代码
  • 不要在render函数中使用高阶组件
TODO复制代码
  • 必须将静态方法做拷贝
TODO复制代码
  • Refs属性不能传递
TODO复制代码

无ES6创建React Component

  • create-react-class
TODO复制代码

动态引入 dynamic import

  • React Loadable
TODO复制代码

受控制组件 or 非受控制组件

TODO复制代码

转载地址:http://jegdo.baihongyu.com/

你可能感兴趣的文章
怎样使用原型设计中的组件样式功能
查看>>
python threading
查看>>
谷安天下2013年6月CISA考前辅导 第一季
查看>>
ARM程序规范
查看>>
Qt下的OpenGL 编程(8)文字、FPS、动画
查看>>
记一次mapreduce读取不到输入文件的问题
查看>>
我的友情链接
查看>>
在普通台式机上搭建服务器虚拟化架构Esxi平台
查看>>
电话线路 30B+D 名词解释
查看>>
吉炬消费系统软件输入密码后无法打开软件界面故障处理
查看>>
Hibernate学习系列————注解一对多双向实例
查看>>
Cannot load from mysql.proc
查看>>
网络运维之 EX4200消除var分区使用过高的告警
查看>>
【最好的流程是没有流程】
查看>>
Apache Thrift 教程
查看>>
Python Epoll
查看>>
AS3歌词同步详解
查看>>
单例模式
查看>>
Linux环境NetBeans字体通用抗据齿解决方法
查看>>
Eclipse的花括号(brace)的输入偏好问题
查看>>