react扩展

react扩展

  • setState
    • 对象式的setState
    • 函数式的setState
  • 组件懒加载
  • Hooks
    • useState基本使用
    • effectHook的基本使用
    • refHooks
    • context
      • context传递值
      • context接受值
    • pureComponent
    • ErrorBoundary

setState

对象式的setState

在我的另一篇文章react入门到入魔中,只用到了setState最简单的用法

	this.setState({xxx:'新值'});

由于setState是一个异步更新方法,所以以下写法是拿不到state更新之后的值的

	this.setState({xxx:'新值'});
	console.log(this.state)

实际上,完整的用法如下

	this.setState({xxx:'新值'}, () => {更新之后的回调函数});

函数式的setState

函数式的setState接收到两个参数,state和props,函数的返回值将作为最新的state状态

	this.setState(
      (state, props) => {
        return {
          xxx: "新值",
        };
      },
      () => {
        console.log("更新之后的回调");
      }
    );

组件懒加载

组件懒加载一般指路由组建的懒加载,指在未渲染到该路由组件时,不应该提前渲染到页面上。使用方法极其简单。

	// 首先修改路由组件的引入方式
	// 修改前
	
	// 现在引入容器组件
	// import Counter from "./container/Count/index";
	// import Result from "./container/Result/index";
	// import User from "./container/User/index";

	// 修改之后
	import { lazy, Suspense } from "react";
	const Counter = lazy(() => import("./container/Count/index"));
	const Result = lazy(() => import("./container/Result/index"));
	const User = lazy(() => import("./container/User/index"));

import可以作为一个方法引入(ES6标准,按需引入),同时,因为是按需引入,那么就要考虑引入失败的情况,所以要对组件提供一个容错组件。
将路由组件用suspense组件包裹起来

	<Suspense fallback={<h1>计算器页面正在加载中</h1>}>
	    <Counter></Counter>
	    <Result></Result>
    </Suspense>
    <Suspense fallback={<h1>用户页面正在加载中</h1>}>
        <User></User>
    </Suspense>

实际页面效果
react扩展_第1张图片

Hooks

react16.8之后新增的特性,可以让函数式组件使用state及react特性
几个常见的Hooks

useState基本使用

可以让函数式组件使用state

	import { useState } from "react";
	function HooksDemo() {
	  const [myName, updateName] = useState("wxs");
	  const changeName = () => {
	    updateName('我的新名字')
	  };
	  return (
	    <div>
	      一个简单的Hooks测试 看看我的名字的值{myName}
	      <button onClick={changeName}>点击我改一个名字</button>
	    </div>
	  );
	}
	export default HooksDemo;

其中updateName还可以接受一个函数,当更新之后的值需要以原来的值为基础进行更改时使用

	updateName((oldValue) => (oldValue + 1))

effectHook的基本使用

可以让函数式组件使用生命周期,useEffect函数接受两个参数,第一个参数是一个回调函数,在组件挂载完毕之后调用。第二个参数是一个数组,在数组中的state对象发生改变时也会调用第一个回调函数

	const [myName, updateName] = useState("wxs");
	  const changeName = () => {
	    updateName('我的新名字')
	  };
	  useEffect(() => {
	    console.log("组件挂载成功或者myName变化了")
	  },[myName])   

Tips: effctHook第一个回调函数返回一个函数将作为componentWillUnMount的回调

refHooks

在函数式组件中使用ref

	const myButton = useRef()
	<button onClick={changeName} ref={myButton}>点击我改一个名字</button>

context

用于跨层级组件间通信。这里以三层嵌套结构为
react扩展_第2张图片
代码结构如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
react扩展_第3张图片
如果想从A传递数据到C,用redux显得小题大作,用props又显得太过麻烦。这时可以用到context

context传递值

1、新建一个context变量 —> 2、 provider包裹父组件提供值

	// 因为待会取值的时候要用到同一个context对象,所以在这里通过export暴露出去
	export const MyContext = createContext();
	// provider必须要用value属性传递值,不然会报错
	<MyContext.Provider value='我传递一个值看看'>
       <ComponentB></ComponentB>
    </MyContext.Provider>

context接受值

1、第一种方法(仅类式组件能使用)
在类式组件中定义私有变量contextType

	// 导入context对象
	export const MyContext = createContext();
	// 注意变量名一定要是coontextType,不然无法传值
	static contextType = MyContext;
	如此操作之后就可以通过类组件的this.context取值了
	console.log(this.context);

在这里插入图片描述
2、第二种方法
同样的需要先导入context对象,然后在对象的consumer标签中可以自由使用传递的值

	import { MyContext } from "../ComponentA/ComponentA";
	<MyContext.Consumer>
      { value => `${value}` }
    </MyContext.Consumer>

pureComponent

目前我们所写的所有组件都是继承于react的component。
在这里插入图片描述
对于一般的component存下如下的问题,只要执行setState就会执行组件的render函数。
react扩展_第4张图片
但是对此会带来严重的效率问题。图中只涉及到了一个子组件,万一一个组件内有2-30个子组件,当父组件设置setState({})并没有改变任何值但缺引发了十几个子组件的render函数。
原因是 component生命周期shoulComponentUpdate总是返回ture。
对此,我们可以重写shouldComponentsUpdate的判断逻辑。在没有属性更新的时候返回false,不触发组件更新。而对此我们要写判断两个对象是否相等的代码逻辑。像这样

	const currentState = this.state;
    const currentStateKeys = Object.keys(currentState);
    const nextStateKeys = Object.keys(nextState);
    if (nextStateKeys.length !== currentStateKeys.length) {
      // 如果前state和后state对象含有键长度不一样,那么可以肯定state发生了改变
      return true;
    } else {
      let shouldUpdate = false
      // 键数组长度一样
      currentStateKeys.forEach((currentKey) => {
        if (!nextStateKeys.includes(currentKey)) {
          // 如果新state有原state不存在的key值,那么可以说明state发生了改变
          shouldUpdate = true;
        }
      });
      // 前后state键长度一样,且键名完全一致
      currentStateKeys.forEach((currentKey) => {
        if (currentState[currentKey] !== nextState[currentKey]) {
          // 同键名,值不同 state发生了改变
          shouldUpdate =  true;
        }
      });
      return shouldUpdate;
    }

或者我们可以选择另一种方法。
将component换成pureComponent
在这里插入图片描述

ErrorBoundary

错误边界:对子组件的容错处理,看,在A组件中嵌套一个B组件
react扩展_第5张图片
b组件结构如下

	import React, { Component } from "react";
export default class ComponentB extends Component {

  state = {
    name: "wxs",
    studentList: [
      {
        id: 1,
        name: "wxs1",
      },
      {
        id: 2,
        name: "wxs2",
      },
    ],
  };
  render() {
    return (
      <div>
        我是一个B组件
        <div>
          {this.state.studentList.map((student) => (
            <p key={student.id}>{student.name}</p>
          ))}
        </div>
      </div>
    );
  }
}

很正常的显示在页面上
react扩展_第6张图片
但如果因为某些原因,导致studentLIst不是一个数组,而是其他类型的变量比如字符串

	studentList:'aaa'

而导致页面无法正常渲染时,可以通过其父组件的边界容错处理错误信息以及异常情况。
以上为例。

	export default class ComponentA extends PureComponent {
  static getDerivedStateFromError(err) {
    return {
      componentError: {
        hasError: true,
        errorMsg: err,
      },
    };
  }
  render() {
    return (
      <div>
        我是一个A组件 
        { this.state?.componentError?.hasError ? <div>肯定是b组件出错了</div> : <ComponentB />}
      </div>
    );
  }
}

页面容错处理展示
react扩展_第7张图片

你可能感兴趣的:(mysql,windows,big,data)