10分钟学会React Context API

Create-react-app来学习这个功能: 注意下面代码红色的即可,非常简单.

在小项目里Context API完全可以替换掉react-redux.

修改app.js

import React, { lazy, useState } from "react";
import { Button } from 'antd';
import { HashRouter as Router, Route, Link } from 'react-router-dom';

import GlobalContext from './globalContext' // 导入全局context
import './App.css';
//import Hehe from './hehe'  //直接导入会让包变大,使用lazy会让包变小
const Hehe = lazy(() => import("./hehe"));
const T2 = lazy(() => import("./T2"));
const Reg = lazy(() => import(/* webpackChunkName: "reg" */'./reg'));


//普通的组件
const PageHeaderWrapper = (prop) => {
  console.log("子组件刷新...");
  return (
    <>
      <div>PageHeaderWrapper Memo:{prop.loading} {new Date().getTime()}</div>
      <div>{prop.content}</div>
    </>
  )
}

// React.memo对PageHeaderWrapper组件进行包装,让这个PageHeaderWrapper组件进行包装组件变成可控组件
// React.memo()可接受2个参数,第一个参数为纯函数的组件,第二个参数用于对比props控制是否刷新,true不更新,与shouldComponentUpdate()功能类似。
const Memo = React.memo(PageHeaderWrapper, (prevProps, nextProps) => {
  console.log(prevProps, nextProps);
  //return true;
  return prevProps.loading === nextProps.loading
}

);

//定义一个方法用来测试接受 Provider
const ChangeName = (props) => {
  return (
    <GlobalContext.Consumer>
      {context =>
        <div>{props.title}: {context.name}</div>
      }
    </GlobalContext.Consumer>
  )
}
//产生一个随机内容的obj 只是为了示例使用
const rand = () => {
  const a = parseInt(Math.random() * 4, 10);
  return { name: "aaa" + a }
}

//入口文件
const App = () => {
  const [value, setValue] = useState({ name: "aaa" });

  return (
    <GlobalContext.Provider value={value}>
      <div className="App">
        <header className="App-header">
          <Memo loading={value.name} content='Memo content' />
          <Button type="primary" onClick={() => setValue(rand)}>Hehe</Button>
          <p>
            Provider: {value.name}
          </p>


          <ChangeName title="changeName"></ChangeName>

          <React.Suspense fallback="T2 loading...">
            <Hehe />
          </React.Suspense>

          <Router>
            <Link to="/reg">
              <div>会员注册</div>
            </Link>
            <Link to="/t2">
              <div>跳转到异步组件t2</div>
            </Link>

            <Route exact path='/' component={() => <React.Suspense fallback="T2 loading..."> <T2 /> </React.Suspense>} />
            <Route path='/t2' component={() => <React.Suspense fallback="T2 loading..."> <T2 /> </React.Suspense>} />
            <Route path='/reg' component={() => <React.Suspense fallback="Reg loading..."> <Reg /> </React.Suspense>} />
            {/* <Route path='/regsync' component={Reg1} /> 使用同步组件会让包变大 */}

          </Router>

        </header>



      </div>

    </GlobalContext.Provider>
  )
}

export default App;

reg.js

import React from "react";
import axios from "axios";
import { Form, Icon, Input, Button, Checkbox, Table } from 'antd';



  
  const columns = [
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: 'Email',
      dataIndex: 'email',
      key: 'email',
    },
    {
      title: 'Ip',
      dataIndex: 'ip',
      key: 'ip',
    },
  ];

//不要在使用class组件,使用函数式组件来,具体看T2.js

class NormalLoginForm extends React.Component {
    constructor(props){
        super(props)
        this.state = {
              dataSource:[]
        }

    }
    handleSubmit = e => {
      e.preventDefault();
      //开始验证表单,如果原因 通过执行回调发送ajax
      this.props.form.validateFields((err, values) => {
        if (!err) {
          console.log('表单里的值: ', values);
          let request=values;
          request.test="test";
          //向后台发送
          axios.get("https://www.easy-mock.com/mock/5a3a2fc5ccd95b5cf43c5740/table_list",{
            params: request
          }).then(response=>{
            //后台返回的值:
            console.log(response.data);
            this.setState({dataSource:response.data.data})
          }).catch(e=>{
              //请求网络原因等失败了处理
          });
        }
      });
    };
  
    render() {
      const { getFieldDecorator } = this.props.form;
      return (
          <div  >
        <Form onSubmit={this.handleSubmit} className="login-form">
          <Form.Item>
            {getFieldDecorator('username', {
              rules: [{ required: true, message: 'Please input your username!' }],
            })(
              <Input
                prefix={<Icon type="user" rgba(0,0,0,.25)' }} />}
                placeholder="Username"
              />,
            )}
          </Form.Item>
          <Form.Item>
            {getFieldDecorator('password', {
              rules: [{ required: true, message: 'Please input your Password!' }],
            })(
              <Input
                prefix={<Icon type="lock" rgba(0,0,0,.25)' }} />}
                type="password"
                placeholder="Password"
              />,
            )}
          </Form.Item>
          <Form.Item>
            {getFieldDecorator('remember', {
              valuePropName: 'checked',
              initialValue: true,
            })(<Checkbox>Remember me</Checkbox>)}
    
            <Button type="primary" htmlType="submit" className="login-form-button">
              Log in
            </Button>
            
          </Form.Item>
        </Form>
        <Table dataSource={this.state.dataSource} columns={columns} #fff'}} />
        </div>
      );
    }
  }
  
  const Reg = Form.create({ name: 'normal_login' })(NormalLoginForm);

export default Reg;

T2.js

import React, {useState, useEffect} from "react";
import axios from "axios";

//组件 里可以使用state,这样就可以不在使用class
const T2=(prop)=>{
   const [message, setMessage]=useState(()=>{
        return 'start...';
   });

    function temp(){
        axios.get('http://route.showapi.com/1764-1').then(response=> {
            console.log(response.data.showapi_res_error);
            setMessage(response.data.showapi_res_error);
        })
   }   
   useEffect( () => {
         temp()
      }, [message]);  

   // 给useEffect传第二个参数。用第二个参数来告诉react只有当这个参数的值发生改变时,才执行我们传的副作用函数(第一个参数)。
   return (
     <>
       <div>T2. message: {message}</div>   
     </>
    )
}

export default T2;

GlobalContext.js

import React from 'react'
const GlobalContext = React.createContext();
export default GlobalContext;