05-React 扩展

33 阅读3分钟

React 扩展

01-setState

import React, { Component } from "react";

export default class Demo1 extends Component {
  state = { count: 0 };
  add = () => {
    const { count } = this.state;
    // 第一种写法,(对象式的 setState)
    // setState是一个同步的方法,
    // 但是setState引起的React后续更新的动作是异步的,可以回调处理
    // this.setState(
    //   {
    //     count: count + 1,
    //   },
    //   () => {
    //     console.log("我改完了"); // 后打印
    //   }
    // );
    // console.log("我改完了么"); // 先打印

    // 第一种写法,(函数式的 setState)
    this.setState(
      (state) => ({ count: state.count + 1 }),
      () => {
        console.log("我改完了"); // 后打印
      }
    );
    console.log("我改完了么"); // 先打印
  };
  render() {
    return (
      <div>
        <h1>当前求和: {this.state.count}</h1>
        <button onClick={this.add}>点我加1 </button>
      </div>
    );
  }
}

02-lazyLoad

//创建外壳组件APP
import React, { Component, lazy, Suspense } from "react";
import { NavLink, Route } from "react-router-dom";
// import About from "./About";
// import Home from "./Home";
const Home = lazy(() => import("./Home"));
const About = lazy(() => import("./Home"));
export default class Demo2 extends Component {
  render() {
    return (
      <div>
        <h1>我是APP</h1>
        {/* 一个项目只允许有一个 BrowserRoute,把这个写到index.js里面 */}
        {/* 注册跳转标签 */}
        <NavLink to="/about" activeClassName="active">
          {" "}
          About{" "}
        </NavLink>
        <NavLink to="/home"> Home </NavLink>
        {/* 注册路由 */}
        <Suspense fallback={<h2>Loading..</h2>}>
          <Route path="/about" component={About} />
          <Route path="/home" component={Home} />
        </Suspense>
      </div>
    );
  }
}

03-hooks

import React, { Component, useState } from "react";
import ReactDOM from "react-dom";
// 类式组件
// export default class Demo3 extends Component {
//   state = { count: 1, timer: null };
//   myRef = React.createRef();
//   add = () => {
//     this.setState((state) => ({ count: state.count + 1 }));
//   };
//   show = () => {
//     alert(this.myRef.current.value);
//   };
//   unmount = () => {
//     ReactDOM.unmountComponentAtNode(document.getElementById("root"));
//   };
//   componentDidMount() {
//     this.state.timer = setInterval(() => {
//       this.setState((state) => ({ count: state.count + 1 }));
//     }, 1000);
//   }
//   componentWillUnmount() {
//     clearInterval(this.state.timer);
//   }
//   render() {
//     return (
//       <div>
//         <input type="text" ref={this.myRef} />
//         <h2>{this.state.count}</h2>
//         <button onClick={this.add}>点我+1</button>
//         <button onClick={this.unmount}>卸载组件</button>
//         <button onClick={this.show}>点击提示</button>
//       </div>
//     );
//   }
// }

// 函数式组件
function Demo3() {
  // useState
  // state 每次的变化都会重新进到这里面
  // 但是 React 内部处理了,不会每次都把 count 重置
  const [count, setCount] = React.useState(0);
  function add() {
    // setCount(count + 1);     // 第一种写法
    setCount((count) => count + 1); // 第二种写法
  }
  function unmount() {
    ReactDOM.unmountComponentAtNode(document.getElementById("root"));
  }
  // useEffect
  React.useEffect(() => {
    // 这个函数相当于 componentDidMount
    let timer = setInterval(() => {
      setCount((count) => count + 1);
    }, 1000);
    // 这个返回的函数  相当于 componentWillUnmount
    return () => {
      clearInterval(timer);
    };
  }, []);

  const myRef = React.useRef();
  function show() {
    alert(myRef.current.value);
  }
  return (
    <div>
      <input type="text" ref={myRef} />
      <h2>求和:{count}</h2>
      <button onClick={add}>点我+1</button>
      <button onClick={unmount}>卸载组件</button>
      <button onClick={show}>点我提示数据</button>
    </div>
  );
}
export default Demo3;

04-Fragment

import React, { Component, Fragment } from "react";

export default class Demo4 extends Component {
  render() {
    return <Fragment key={1}>1111</Fragment>; // 需要加属性的时候这个 Fragment 就很好用了
    // <div id="root"><div>1111</div></div>

    // return <div>1</div>;
    // <div id="root"><div><div>1</div></div></div>
  }
}

05-Context

import React, { Component } from "react";
// 创建 createContext 对象
const UsernameContext = React.createContext();
const { Provider, Consumer } = UsernameContext;
class B extends Component {
  render() {
    return (
      <div style={{ border: "1px solid blue", margin: "20px" }}>
        <h3>我是B组件</h3>
        <h4>我的从A接收到的用户名是</h4>
        <C />
      </div>
    );
  }
}
// C 类式组件
// class C extends Component {
//   // 1. 声明接收 contextType
//   static contextType = UsernameContext;
//   render() {
//     console.log(this.context);
//     return (
//       <div style={{ border: "1px solid green", margin: "20px" }}>
//         <h3>我是C组件</h3>
//         <h4>我的从A接收到的用户名是 {this.context.name}</h4>
//         <h4>我的从A接收到的年龄是 {this.context.age}</h4>
//       </div>
//     );
//   }
// }
// C 函数式组件
function C(params) {
  return (
    <div style={{ border: "1px solid green", margin: "20px" }}>
      <h3>我是C组件</h3>
      <h4>
        我的从A接收到的用户名是
        <Consumer>
          {(value) => {
            return value.name;
          }}
        </Consumer>
      </h4>
      <h4>
        我的从A接收到的年龄是
        <Consumer>
          {(value) => {
            return value.age;
          }}
        </Consumer>
      </h4>
    </div>
  );
}

export default class A extends Component {
  state = { name: "YO", age: 12 };
  render() {
    const { name, age } = this.state;
    return (
      <div style={{ border: "1px solid red", margin: "20px" }}>
        <h3>我是A组件</h3>
        <h4>我的用户名是 {this.state.name}</h4>
        <Provider value={{ name, age }}>
          <B />
        </Provider>
      </div>
    );
  }
}

06-optimize

import React, { Component, PureComponent } from "react";

export default class Parent extends PureComponent {
  state = { carName: "别克", stus: ["1", "2"] };
  changeCar = () => {
    // 这样写就不行了
    // const obj = this.state;
    // obj.carName = "迈巴赫";
    // this.setState(obj);
    //
    //
    // 这样写是生效的
    // this.setState({
    //   carName: "迈巴赫",
    // });
  };
  addStu = () => {
    // 这样写是无效的
    // const { stus } = this.state;
    // stus.unshift("3");
    // this.setState({stus});
    //
    //
    // 这样写是生效的
    const { stus } = this.state;
    this.setState({ stus: ["3", ...stus] });
  };
  //   shouldComponentUpdate(nextProps, nextState) {
  //     return !(this.state.carName === nextState.carName);
  //   }
  render() {
    const { carName, stus } = this.state;
    console.log("Parent---------------------");
    return (
      <div style={{ border: "1px solid blue", margin: "20px" }}>
        <h3>我是 Parent 组件</h3>
        <h4>我的车名字是 {carName}</h4>
        <button onClick={this.changeCar}>换车</button>
        <button onClick={this.addStu}>添加学生</button>
        {stus.map((el) => {
          return <span key={el}>{el}---</span>;
        })}
        {/* <Child /> */}
        <Child carName={carName} />
      </div>
    );
  }
}
class Child extends PureComponent {
  //   shouldComponentUpdate(nextProps, nextState) {
  //     return !(this.props.carName === nextProps.carName);
  //   }
  render() {
    console.log("Child---------------------");
    return (
      <div style={{ border: "1px solid red", margin: "20px" }}>
        <h3>我是 Child 组件</h3>
        <h4>我接到的车是 {this.props.carName}</h4>
      </div>
    );
  }
}

07-renderProps

import React, { Component } from "react";

export default class Parent extends Component {
  render() {
    return (
      <div style={{ border: "1px solid green", margin: "20px" }}>
        <h2>Parent</h2>
        {/* <A>
          <B />
        </A> */}
        <A render={(name) => <B name={name} />} />
      </div>
    );
  }
}
class A extends Component {
  state = { name: "tom" };
  render() {
    console.log(this.props.children);
    const { name } = this.state;
    return (
      <div style={{ border: "1px solid green", margin: "20px" }}>
        <h2>A</h2>
        {this.props.render(name)}
      </div>
    );
  }
}

class B extends Component {
  render() {
    console.log("B---->render");
    return (
      <div style={{ border: "1px solid green", margin: "20px" }}>
        <h2>B</h2>
        <h3>从上层父组件拿到的名字: {this.props.name}</h3>
      </div>
    );
  }
}

08-ErrorBoundary

Parent.jsx

import React, { Component } from "react";
import Child from "./Child";

export default class Parent extends Component {
  state = {
    hasError: "", // 用于标识子组件是否产生错误
  };
  static getDerivedStateFromError(error) {
    console.log(error);
    return {
      hasError: error,
    };
  }
  // 子组件渲染错误的时候会执行这里
  // 一般用于收集错误,反馈给服务器,用于通知编码人员进行问题修复
  componentDidCatch(error, info) {
    console.log(error, info);
    console.log("渲染错误");
  }
  render() {
    return (
      <div>
        <h2>我是 Parent 组件</h2>
        {this.state.hasError ? (
          <h2>当前网络不稳定...请稍后重试....</h2>
        ) : (
          <Child />
        )}
      </div>
    );
  }
}

Child.jsx

import React, { Component } from "react";

export default class Child extends Component {
  state = {
    // users: [
    //   { id: 1, name: 1, age: 1 },
    //   { id: 2, name: 2, age: 2 },
    //   { id: 3, name: 3, age: 3 },
    // ],
    users: "aaa",
  };
  render() {
    return (
      <div>
        <h2>我是 Child 组件</h2>
        {this.state.users.map((user) => {
          return (
            <h4 key={user.id}>
              {user.name}-----{user.age}
            </h4>
          );
        })}
      </div>
    );
  }
}