• React入门第三天


    1. 生命周期

    生命周期方法

    ⽣生命周期⽅方法,⽤用于在组件不不同阶段执⾏行行⾃自定义功能。在组件被创建并插⼊入到 DOM 时(即挂载中阶段(mounting) ),组件更更新时,组件取消挂载或从 DOM 中删除时,都有可以使⽤用的⽣生命周期⽅方法。

    React V16.3之前的生命周期

    img

    V16.4之后的⽣生命周期:

    img

    V17可能会废弃的三个⽣生命周期函数⽤用getDerivedStateFromProps替代,⽬目前使⽤用的话加上 UNSAFE_: componentWillMount componentWillReceiveProps componentWillUpdate 引⼊入两个新的⽣生命周期函数: static getDerivedStateFromProps getSnapshotBeforeUpdate

    如果不不想⼿手动给将要废弃的⽣生命周期添加 UNSAFE_ 前缀,可以⽤用下⾯面的命令。

    npx react-codemod rename-unsafe-lifecycles <path>

    新引入的两个生命周期函数

    getDerivedStateFromProps

    static getDerivedStateFromProps(props, state)

    getDerivedStateFromProps 会在调⽤用 render ⽅方法之前调⽤用,并且在初始挂载及后续更更新时都会被 调⽤用。它应返回⼀一个对象来更更新 state,如果返回 null 则不不更更新任何内容。

    请注意,不不管原因是什什么,都会在每次渲染前触发此⽅方法。这与 UNSAFE_componentWillReceiveProps 形成对⽐比,后者仅在⽗父组件重新渲染时触发,⽽而不不是在内部 调⽤用 setState 时。

    getSnapshotBeforeUpdate

    getSnapshotBeforeUpdate(prevProps, prevState)

    在render之后,在componentDidUpdate之前。 getSnapshotBeforeUpdate() 在最近⼀一次渲染输出(提交到 DOM 节点)之前调⽤用。它使得组件能 在发⽣生更更改之前从 DOM 中捕获⼀一些信息(例例如,滚动位置)。此⽣生命周期的任何返回值将作为参数传 递给 componentDidUpdate(prevProps, prevState, snapshot) 。

    验证生命周期

    范例例:创建LifeCyclePage.js

    import React, { Component } from "react";
    import PropTypes from "prop-types";
    /*
    V17可能会废弃的三个⽣生命周期函数⽤用getDerivedStateFromProps替代,⽬目前使⽤用的话加上
    UNSAFE_:
    - componentWillMount
    - componentWillReceiveProps
    - componentWillUpdate
    */
    export default class LifeCyclePage extends Component {
    static defaultProps = {
    msg: "omg"
    };
    static propTypes = {
    msg: PropTypes.string.isRequired
    };
    constructor(props) {
    super(props);
    this.state = {
    count: 0,
    };
    console.log("constructor", this.state.count);
    }
    static getDerivedStateFromProps(props, state) {
    // getDerivedStateFromProps 会在调⽤用 render ⽅方法之前调⽤用,
    //并且在初始挂载及后续更更新时都会被调⽤用。
    //它应返回⼀一个对象来更更新 state,如果返回 null 则不不更更新任何内容。
    const { count } = state;
    console.log("getDerivedStateFromProps", count);
    return count < 5 ? null : { count: 0 };
    }
    //在render之后,在componentDidUpdate之前。
    getSnapshotBeforeUpdate(prevProps, prevState, snapshot) {
    const { count } = prevState;
    console.log("getSnapshotBeforeUpdate", count);
    return null;
    }
    /* UNSAFE_componentWillMount() {
    //不不推荐,将会被废弃
    console.log("componentWillMount", this.state.count);
    } */
    componentDidMount() {
    console.log("componentDidMount", this.state.count);
    }
    componentWillUnmount() {
    //组件卸载之前
    console.log("componentWillUnmount", this.state.count);
    }
    /* UNSAFE_componentWillUpdate() {
    //不不推荐,将会被废弃
    console.log("componentWillUpdate", this.state.count);
    } */
    componentDidUpdate() {
    console.log("componentDidUpdate", this.state.count);
    }
    shouldComponentUpdate(nextProps, nextState) {
    const { count } = nextState;
    console.log("shouldComponentUpdate", count, nextState.count);
    return count !== 3;
    }
    setCount = () => {
    this.setState({
    count: this.state.count + 1,
    });
    };
    render() {
    const { count } = this.state;
    console.log("render", this.state);
    return (
    <div>
    <h1>我是LifeCycle⻚页⾯面</h1>
    <p>{count}</p>
       <button onClick={this.setCount}>改变count</button>
    {/* {!!(count % 2) && <Foo />} */}
    <Child count={count} />
    </div>
    );
    }
    }
    class Child extends Component {
    UNSAFE_componentWillReceiveProps(nextProps) {
    //不不推荐,将会被废弃
    // UNSAFE_componentWillReceiveProps() 会在已挂载的组件接收新的 props 之前被调⽤用
    console.log("Foo componentWillReceiveProps");
    }
    componentWillUnmount() {
    //组件卸载之前
    console.log(" Foo componentWillUnmount");
    }
    render() {
    return (
    <div
    style={{ border: "solid 1px black", margin: "10px", padding: "10px" }}
    >
    我是Foo组件
    <div>Foo count: {this.props.count}</div>
    </div>
    );
    }
    }

    组件复合

    组件复合 - Composition

    复合组件给与你⾜足够的敏敏捷去定义⾃自定义组件的外观和⾏行行为,这种⽅方式更更明确和安全。如果组件间有公⽤用的⾮非UI逻辑,将它们抽取为JS模块导⼊入使⽤用⽽而不不是继承它。

    不具名

    import React, { Component } from "react";
    import TopBar from "../components/TopBar";
    import BottomBar from "../components/BottomBar";
    export default class Layout extends Component {
    componentDidMount() {
    const { title = "商城" } = this.props;
    document.title = title;
    }
    render() {
    const { children, showTopBar, showBottomBar } = this.props;
    console.log("children", children);
    return (
    <div>
    {showTopBar && <TopBar />}
    {children.content}
    {children.txt}
    <button onClick={children.btnClick}>button</button>
    {showBottomBar && <BottomBar />}
    </div>
    );
    }
    }
    import React, { Component } from "react";
    import Layout from "./Layout";
    export default class UserPage extends Component {
    render() {
    return (
    <Layout showTopBar={true} showBottomBar={true} title="⽤用户中⼼心">
    <div>
    <h3>UserPage</h3>
    </div>
    </Layout>
    );
    }
    }

    具名

    传个对象进去:

    import React, { Component } from "react";
    import Layout from "./Layout";
    export default class HomePage extends Component {
    render() {
    return (<Layout showTopBar={false} showBottomBar={true} title="商城⾸首⻚页">
    {/* <div>
    <h3>HomePage</h3>
    </div> */}
    {{
    content: (
    <div>
    <h3>HomePage</h3>
    </div>
    ),
    txt: "这是个⽂文本",
    btnClick: () => {
    console.log("btnClick");
    }
    }}
    </Layout>
    );
    }
    }

    实现⼀一个简单的复合组件,如antD的Card

    import React, { Component } from 'react'
    function Card(props) {
    return <div xu="card">
    {
    props.children
    }
    </div>
    }
    function Formbutton(props) {
    return <div className="Formbutton">
    <button onClick={props.children.defaultBtns.searchClick}>默认查询</button>
    <button onClick={props.children.defaultBtns.resetClick}>默认重置</button>
    {
    props.children.btns.map((item, index) => {
    return <button key={'btn' + index} onClick={item.onClick}>{item.title}
    </button>
    })
    }
    </div>
    }
    export default class CompositionPage extends Component {
    render() {
    return (
    <div>
    <Card>
    <p>我是内容</p>
    </Card>
    CompositionPage
    <Card>
    <p>我是内容2</p>
    </Card>
    <Formbutton>
    {{
    /* btns: (
    <>
    <button onClick={() => console.log('enn')}>查询</button>
    <button onClick={() => console.log('enn2')}>查询2</button>
    </>
    ) */
    defaultBtns: {
    searchClick: () => console.log('默认查询'),
    resetClick: () => console.log('默认重置')
    },
    btns: [
    {
    title: '查询',
    onClick: () => console.log('查询')
    }, {
    title: '重置',
    onClick: () => console.log('重置')
    }
    ]
    }}
    </Formbutton>
    </div>
    )
    }
    }

    redux

    你可能不不需要redux

    Redux 是负责组织 state 的⼯工具,但你也要考虑它是否适合你的情况。不不要因为有⼈人告诉你要⽤用 Redux 就去⽤用,花点时间好好想想使⽤用了了 Redux 会带来的好处或坏处。 在下⾯面的场景中,引⼊入 Redux 是⽐比较明智的:

    你有着相当⼤大量量的、随时间变化的数据; 你的 state 需要有⼀一个单⼀一可靠数据来源; 你觉得把所有 state 放在最顶层组件中已经⽆无法满⾜足需要了了。 某个组件的状态需要共享。

    1614215886864

    redux

    redux 是 JavaScript应⽤用的状态容器器,提供可预测化的状态管理理。它保证程序⾏行行为⼀一致性且易易于测试。

    1614215932166

    安装redux

    ⽤用⼀一个累加器器举例例

    1. 需要⼀一个store来存储数据

    2. store⾥里里的reducer初始化state并定义state修改规则

    3. 通过dispatch⼀一个action来提交对数据的修改

    4. action提交到reducer函数⾥里里,根据传⼊入的action的type,返回新的state

      ReduxPage.js

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

    export default class ReduxPage extends Component{
       componentDidMount(){
           store.subscribe(()=>{
               this.forceUpdate();
          })
      }
       add=()=>store.dispatch({type:"ADD"});
       minus=()=>store.dispatch({type:"MINUS"});
       render(){
           return (
               <div>ReduxPage
                   <p>{store.getState()}</p>
                   <button onClick={this.add}>add</button>
                   <button onClick={this.minus}>minus</button>
               </div>
               
          );
      };
    }

     

    reduxStore.js

    import { createStore } from "redux";

    const  createReducer=(state=0,action)=>{
       switch (action.type) {//这里的type匹配的是type
           case "MINUS":
               return state-1;
           case "ADD":
               return state+1;
       
           default:
               return state;
      }
    }

    const store=createStore(createReducer);
    export default store;

    index.js

    const context=<div>
       <ReduxPage /></div>;

    const render = ()=>{
       ReactDOM.render(
       context,
       document.querySelector('#root')
      )
      };
    render();
    store.subscribe(render);

    检查点

    1. createStore 创建store

    2. reducer 初始化、修改状态函数

    3. getState 获取状态值

    4. dispatch 提交更更新

    5. subscribe 变更更订阅

      react-redux

    安装

    npm install react-redux --save

    使用react-redux

    react-redux提供了了两个api

    1. Provider 为后代组件提供store

    2. connect 为组件提供数据和变更更⽅方法 全局提供store, index.js

      ./store/index.js

      import { createStore } from "redux";//这里记得导入redux

      const  createReducer=(state=0,action)=>{
         switch (action.type) {//这里的type匹配的是type
             case "MINUS":
                 return state-1;
             case "ADD":
                 return state+1;
         
             default:
                 return state;
        }
      }

      const store=createStore(createReducer);
      //用redux创建store
      export default store;

      ReduxPage.js

    import React,{Component} from 'react';
    import {connect} from "react-redux";

    class ReduxPage extends Component{
      render(){
          const {num,add,minus}=this.props;//从props中得入参数,store中取
          return (
              <div>
                  <h1>reduxPage</h1>
                  <h3>{num}</h3>
                  <button onClick={add}>add</button>
                  <button onClick={minus}>minus</button>
              </div>
          );
      }
    }

    const mapStateToProps = state => {
      return {
          num:state,
      }
    }//派发state

    const mapDispatchToProps ={
      add:()=>{return {type:"ADD"};},
      minus:()=>{return {type:"MINUS"}}
    }//派发dispatch
    //连接state和dispatch用来应对传入的store
    export default connect(mapStateToProps, mapDispatchToProps)(ReduxPage);

     

  • 相关阅读:
    mitmproxy的安装和使用
    CMake优先链接静态库
    IPv6与IPv4的兼容
    OpenSSL证书认证过程
    Lua os.clock在win和linux下的差异
    FocalLoss的pytorch代码实现
    单词解释
    将分割图和原图合在一起
    colab如何使用tensorboard
    PyTorch模型加载与保存的最佳实践
  • 原文地址:https://www.cnblogs.com/anatkh/p/14450432.html
Copyright © 2020-2023  润新知