React 扩展、hooks的使用、路由懒加载、组件优化/传值(笔记)

文章目录

      • 1. setState
        • 1.1 setState 的两种写法
        • 1.2 对象式
        • 1.3 函数式
      • 2. lazyLoad(路由懒加载)
      • 3. hooks
        • 3.1 State Hook
        • 3.2 Effect Hook
        • 3.3 Ref Hook
      • 4. Fragment(虚拟DOM)
      • 5. Context(祖孙传值)
      • 6. 组件优化
        • 6.1 Component 的2个问题
        • 6.2 解决方案
      • 7. Render Props(逆向传值)
      • 8. 错误边界
      • 9. 组件通信

1. setState

1.1 setState 的两种写法

  • 对象式
  • 函数式

1.2 对象式

// count 初始值为 0
let { count } = this.state
this.setState({
  count: count + 1
  // 第二个参数为一个可选的回调函数,在数据更新完成之后才会执行
}, () => {
  console.log(count) // 1 
})
console.log(count) // 0

1.3 函数式

// 对象式其实是函数式的语法糖
this.setState((state, props) => {
  return {
    count: state.count + 1 // 返回一个新的状态
  }
},[callback]) // 和对象式的第二个参数一样

2. lazyLoad(路由懒加载)

import React, { Component, lazy, Suspense } from "react";
import { Route, NavLink } from "react-router-dom";

// 路由懒加载
let About = lazy(() => import("./components/About/About"));
let Home = lazy(() => import("./components/Home/Home"));

export default class App extends Component {
  render() {
    return (
      <div className="App">
        <div>
          <NavLink to="/demo/about" children="About" />
          <NavLink to="/demo/home" children="Home" />
        </div>
        <div className="content">
          // 当组件还没有加载回来时,显示fallback中的组件/DOM元素
          <Suspense fallback={<h1>loading...</h1>}>
            <Route path="/demo/about" component={About} />
            <Route path="/demo/home" component={Home} />
          </Suspense>
        </div>
      </div>
    );
  }
}

3. hooks

3.1 State Hook

// 可以使用 React.useState、也可以直接导入 useState
import React, { useState } from "react";

export default function App() {
  // [数据, 修改数据的方法]
  let [count, setCount] = React.useState(0);
  let [arr, setArr] = useState([{name: "小红", age: 18}]);

  function add() {
    // 传入要修改的数据
    setCount(count + 1);
  }

  function addInfo() {
    // 要修改的数据,会替换掉原数据
	setArr([...arr, {name: "小黄", age: 19}])
  }

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={add}>点我加1</button>
      <button onClick={addInfo}>点我加添加信息</button>
    </div>
  );
}

3.2 Effect Hook

import { useEffect } from "react"

export default function App() {
  let [count, setCount] = React.useState(0);

  // 用于模拟类组件中的生命周期钩子
  useEffect(() => {
    // 组件初始化时的操作、类似于 componentDidMount
    return () => {
      // 组件销毁时的操作,类似于 componentWillUnmount
    }
    // 不写 [] 表示任何数据更新都会触发回调,写 [] 可以指定任意数量、数据更新的回调,比如:[count] count 数据更新时触发
  },[]) // 用于检测对应数据的更新,类似于 componentDidUpdate

  function add() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={add}>点我加1</button>
    </div>
  );
}

3.3 Ref Hook

import { useRef } from "react"
// 和 createRef 用法一样

4. Fragment(虚拟DOM)

// Fragment 和 vue 中的 template 很相似
import { Fragment } from "react"

...render(){
  // 在页面中不会生成dom,也可以使用 <> 效果一样,但它并不支持 key 或属性
  return <Fragment></Fragment>
}

5. Context(祖孙传值)

// 用于祖孙组件之间的传值
import { createContext, useContext } from "react";

// 创建 context
const MyContext = createContext();
// Provider:传入的数据,Consumer:接收的数据
const { Provider, Consumer } = MyContext;

function App() {
  return (
	<div>
	  // 只可以写 value
	  <Provider value="要传入的数据">
	    // 后代组件	
	  </Provider>
	</div>
  )
}

// 后代组件1
function Demo1(){
  return (
    <div>
      <Consumer>
        {(value) => {
          // value:接收到的数据
        }}
      </Consumer>
    </div>
  )
}

// 后代组件2
function Demo2() {
  // 接收到的数据
  const value = useContext(MyContext)
  return <div></div>
}

6. 组件优化

6.1 Component 的2个问题

  1. 只要执行了 setState(),即使不改变状态数据,组件也会重新 render
  2. 只要当前组件重新 render,子组件也会重新 render

6.2 解决方案

只有当前组件的 state 或 props 修改时,才会 render

  1. 设置 shouldComponentUpdate 声明周期方法
    shouldComponentUpdate(nextState, nextProps) {
      // 对比 this.state、nextState 和 this.props、nextProps
      // 如果改变了就返回 true,如果没有改变就返回 false
    } 
    
  2. 使用 PureComponent
    import { PureComponent } from "react"
    class App extends PureComponent {
      // 这种已经进行了处理,可以直接使用
      // 但是使用时需要注意两点问题
      //  1. 使用 setState 修改时不要使用同一个地址,地址没变判定为未修改
      //  2. 不要直接在组件标签上,通过回调的形式写 render props,会抵消掉 PureComponent 的作用
    }
    

7. Render Props(逆向传值)

// 这种方式可以向上传递数据,类似于 vue 中的作用域插槽
function App() {
  return (
        <div>
            <p> 我是App组件</p>
            <Child render={(value) => <span>{`name:${value.name},age:${value.age}`}</span>} />
        </div>
    );
}

function Child(props) {
  return (
        <div>
            <p> 我是Child组件</p>
            {props.render({ name: "小红", age: 18 })}
        </div>
    );
}

8. 错误边界

// 用于捕获子组件生命周期的错误,只在生产环境会有效果

class App extends Component {
  // 子组件生命周期出错就会触发
  static getDerivedStateFromError() {
	return {
	  hasError: true
    }
  }

  componentDidCatch() {
    console.log("打印错误信息")
  }
}

9. 组件通信

  • 父子:props、renderProps(逆向传递)
  • 兄弟:redux(集中式管理)、发布订阅
  • 祖孙:redux(集中式管理)、context、发布订阅

你可能感兴趣的:(react,react.js,javascript,前端)