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 id="components-form-demo-normal-login"> <Form onSubmit={this.handleSubmit} className="login-form"> <Form.Item> {getFieldDecorator('username', { rules: [{ required: true, message: 'Please input your username!' }], })( <Input prefix={<Icon type="user" style={{ color: '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" style={{ color: '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} style={{background:'#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;