Fork me on GitHub

react学习(二)(react生命周期,父子组件传参,context,router,reactHook,redux)

生命周期

import React from "react";
class LifeCycle extends React.Component{
    //React.StrictMode会让声明周期执行两次
    constructor(props){
        super(props) 
        this.state={
            count:1
        }
        console.log('生命周期constructor')   //初始化state,绑定this  
    }
    componentDidMount(){
        //渲染完成之后执行
        console.log('生命周期componentDidMount') //发送网络请求
    }
    componentDidUpdate(){
        //更新之后执行
        console.log('生命周期componentDidUpdate') 
    }
    shouldComponentUpdate(){
        //false render就不执行了(阻止渲染)
        console.log('生命周期shouldComponentUpdate') 
        return true
    }
    componentWillUnmount(){
        //销毁之前执行
        console.log('生命周期componentWillUnmount')
    }
    handleClick=()=>{
        this.setState({
            count:this.state.count+1
        })
    }
    render(){
        //渲染执行还没渲染完
        console.log('生命周期render')
        return(
            <div>
                生命周期:{this.state.count}
                <button onClick={this.handleClick}>点击</button>
            </div>
        )
    }
}
export default LifeCycle

 

父子组件传参

函数组件

<IsPorps age={20}></IsPorps>

 

import React from "react";
import PropTypes from 'prop-types'
function IsPorps(props) {
    return (
        <div>
            {props.age}
            {console.log(props)}
        </div>
    )
}
IsPorps.propTypes = {
    age: PropTypes.number //number类型,传string报警告(arry/boll/func/number/object/string)
}
IsPorps.defaultProps = {
    pageSize: 10 //默认值设置
}
export default IsPorps

class组件

<PropsDiv name={'jerry'} age={20} getChild={this.getChild}> 我是子节点(类似于插槽) </PropsDiv>

 

import React from "react";
class PropsDiv extends React.Component {
    constructor(props) {
        //super()是用来继承,不写就用this
        super(props)//constructor中必须要传props,不然拿不到
        console.log(this.props.name)
    }
    setParent = () => {
        this.props.getChild()
    }
    render() {
        return (
            <div>
                <p> class子组件接收参数 : {this.props.name}---{this.props.age}</p>
                <button onClick={this.setParent}>点击传递数据给父组件</button>
                <p>{this.props.children}</p>
            </div>
        )
    }
}
export default PropsDiv

 

Context 是什么?
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。

AppContext
import React from "react";
const AppContext=React.createContext();
export default AppContext
App 
import AppContext from './components/AppContext'//context多层嵌套父组件传给子组件  坑:(必须用同一个声明的AppContext,不能两个文件声明两次)

<AppContext.Provider value={'多层嵌套父组件传给子组件'}>

    <PropsDiv name={'jerry'} age={20} getChild={this.getChild}> 我是子节点(类似于插槽) </PropsDiv>
    
</AppContext.Provider>
ContextDiv
import React, { useContext } from "react";
import AppContext from './AppContext'

//三种接收方法

//第一种AppContext.Consumer
// function ContextDiv() {
//     return (
//         <div>
//             Consumer:
//             <AppContext.Consumer>{data => <span>{data}</span> }</AppContext.Consumer>
//         </div>
//     )
// }

//第二种contextType
// class ContextDiv extends React.Component{
//     static contextType=AppContext
//     render(){
//         return (
//             <div>
//                 Consumer:{this.context}
//             </div>
//         )
//     }   
// }
//第三种useContext
function ContextDiv() {
    var value=useContext(AppContext)
    return (
        <div>
            Consumer:{value}
        </div>
    )
}
export default ContextDiv

 

PropsDiv
import React from "react";
import ContextDiv from "./ContextDiv";
class PropsDiv extends React.Component {
    constructor(props) {
        //super()是用来继承,不写就用this
        super(props)//constructor中必须要传props,不然拿不到
        console.log(this.props.name)
    }
    setParent = () => {
        this.props.getChild()
    }
    render() {
        return (
            <div>
                <p> class子组件接收参数 : {this.props.name}---{this.props.age}</p>
                <button onClick={this.setParent}>点击传递数据给父组件</button>
                <p>{this.props.children}</p>
                <ContextDiv></ContextDiv>
            </div>
        )
    }
}
export default PropsDiv

 

路由

import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import HomeRouter from './components/HomeRouter';
import HistoryRouter from './components/HistoryRouter';

<Router> <Link to='/home'>路由点击去HomeRouter页面</Link> <br /> <Link to='/history'>路由点击去historyRouter页面</Link> <Routes> <Route path='/home' element={<HomeRouter></HomeRouter>}></Route> <Route path='/history' element={<HistoryRouter></HistoryRouter>}></Route> </Routes> </Router>

 

import React from "react";
class HomeRouter extends React.Component{
    render(){
        return(
            <div>HomeRouter页面:高版本中Switch已经被换成了Routes</div>
        )
    }
}
export default HomeRouter

 

import React from "react";
class HistoryRouter extends React.Component{
    render(){
        return(
            <div>HistoryRouter页面:222</div>
        )
    }
}
export default HistoryRouter

 

reactHook
 

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。


useState

import React, { useState } from "react";

function StateHook() {
    //必须在最顶层声明
    const [count, setcount] = useState(1)//第一个参数就是状态,第二个参数就是改变状态方法
    const [list]=useState([{id:1,name:'tom'},{id:2,name:'jerry'}])
    function handleClick() {
        setcount(count+1)
    }
    return (
        <div>
            <p>{count}</p>
            {list.map(item=> <p key={item.id}>{item.name}</p> )}
            <button onClick={handleClick}>点击</button>
        </div>
    )
}
export default StateHook
 
useEffect
import React, { useState, useEffect } from "react";

function StateHook() {
    const [count, setcount] = useState(1)//必须在最顶层声明
    // let [timer] = useState(null)
    function handleClick() {
        setcount(count + 1)
    }
    // function setDate(){
    //     timer = setInterval(function () {
    //         console.log(new Date())
    //     }, 2000)
    // }
    useEffect(() => {
        //useEffect代替三个生命周期函数componentDidMount/componentDidUpdate/componentWillUnmount
        console.log('useEffect代替生命周期函数')
        //第二个参数传[],只代表componentDidMoun钩子函数,可以在这里调用接口,[count]这里传count就会监听count值变化才会执行
    }, [])
    useEffect(() => {
        //useEffect代替三个生命周期函数componentDidMount/componentDidUpdate/componentWillUnmount
        console.log('useEffect代替生命周期函数2222')
        //可以创建多个useEffect   
        // setDate() 
        //清除副作用,不会重复执行多个定时器
        // return () => {
        //     clearInterval(timer)
        // }
    })
    return (
        <div>
            <p>{count}</p>
            <button onClick={handleClick}>点击</button>
        </div>
    )
}
export default StateHook

 

ReduxHook
import React from "react";
import {useSelector,useDispatch} from 'react-redux'
function ReduxHook() {
    //必须在最顶层声明,读取数据
    const value = useSelector((state)=>{
        console.log(state)
        return state.value
    })
    //写入数据
    const disPatch=useDispatch()
    function sendAction(){
        disPatch({
            type:'send_add',
            value:'useDispatch传递数据'
        })
    }
    return (
        <div>
            <p>useSelector读取redux数据:{value}</p>
            <button onClick={sendAction}>useDispatch传递数据</button>
        </div>
    )
}
export default ReduxHook

 

 redux

  1. redux是一个独立专门用于做状态管理的JS库(不是react插件库)
  2. 它可以用在react、angular、vue等项目中,但基本与react配合使用
  3. 作用:集中式管理react应用中多个组件共享的状态
  • redux的结构层次:

  1 store:唯一,只有一颗状态树

  2 resucers:有state,只读的,通过纯函数修改

  3 component:显示与事件的触发

  4 action:动作派发

  • getState 获取状态
  • dispatch 派发动作
  • subscribe 订阅事件

 store/index

import { legacy_createStore as createStore } from "redux";
import { rootReducer } from "./reducer";
const store = createStore(rootReducer)
export default store

 

store/action

const sendAction=()=>{
    return {
        type:'send_type'
    }
}
const sendActionAdd=()=>{
    return {
        type:'send_add'
    }
}
module.exports ={
    sendAction,
    sendActionAdd
}

 

store/reducer

const initState = {
    value: '默认值'
}
const rootReducer = (state = initState, action) => {
    console.log(state, action)
    switch (action.type) {
        case 'send_type':
            return Object.assign({}, state, action)
        case 'send_add':
            return Object.assign({}, state, action)
        default:
            return state
    }
}
module.exports = {
    rootReducer
}

 

import React from 'react';


import store from './store';
import { Provider } from 'react-redux';
import ConnetDiv from './components/ConnectDiv';



class App extends React.Component {
 
  handleAction = () => {
    //发送action
    console.log(store.getState())
    store.dispatch({
      type: 'send_type',
      value: 'redux传值'
    })
  }
  componentDidMount() {
    //监听
    store.subscribe(() => {
      console.log('监听subscribe', store.getState())
      this.setState({})
    })
  }
  render() {
    return (
      <Provider store={store}>

            <h1>redux:</h1>
            <button onClick={this.handleAction}>点击发送action给reducer</button>
            <p>{store.getState().value}</p>

            <h1>react-redux:</h1>
            <ConnetDiv></ConnetDiv>

      </Provider>
    );
  }
}
export default App;

 

import React from "react";
import { connect } from 'react-redux'
class ConnetDiv extends React.Component {
    handleClick=()=>{
        console.log(this.props)
        this.props.sendActionAdd()
    }
    componentDidMount(){
        this.setState({})
    }
    render() {
        return (
            <div>
                <p>react-redux:</p>
                <button onClick={this.handleClick}>发送数据</button>
                <p>接受数据显示:{console.log(this.props)}{this.props.value.value}</p>
            </div>
        )
    }
}
const mapStateToProps=(state)=>{
    return{
        value:state
    }
}
const mapDispatchToProps=(dispatch)=>{
    return{
        sendActionAdd:()=>{
            dispatch({
                type:'send_add',
                value:'connect传值'
            })
        }
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(ConnetDiv)

 

posted @ 2023-04-03 15:13  小白不白10  阅读(116)  评论(0编辑  收藏  举报