【前端】React快速入门+Redux状态管理

news2024/11/24 9:15:54

本文旨在记录react的基础内容,帮助有需要的同学快速上手,需要进一步了解描述更加稳妥和全面的信息,请查阅官方文档
官方文档点击这里进行跳转

React快速入门

先导

react框架

vue,react,angular这几种主流前端框架使用频率较高…本质还是js库。
React.js是一个用于构建用户界面的JavaScript库。它由Facebook开发并开源,被广泛应用于单页应用程序和移动应用开发中。
React采用组件化的开发方式,将用户界面拆分成独立的可重用组件。每个组件都有自己的状态(state)和属性(props),可以根据这些状态和属性来渲染出相应的UI。React使用虚拟DOM(Virtual DOM)来高效地更新和渲染界面,通过对比前后两个虚拟DOM的差异,只更新需要改变的部分,提高了性能。
React的核心思想是声明式编程,开发者只需关注界面应该是什么样子的,而不需要关心具体的更新过程。React还提供了丰富的生命周期方法和钩子函数,可以在组件不同的生命周期阶段执行相应的操作,方便开发者进行状态管理、数据处理和交互逻辑的处理。
React还具有良好的可扩展性和可组合性,可以与其他库和框架(如Redux、React Router等)无缝集成,方便构建复杂的应用程序。

react特点

  • 声明式UI:抛弃命令式的写法,更简单一些
  • 组件化:使用组件构建完整页面,降低了页面的耦合度
  • 跨平台支持:无论是小程序,还是web端,都可以使用react进行开发

react初始搭建

  1. 使用脚手架创建(create react app),打开某个你能记得住具体位置的文件夹,然后在这个文件夹下面使用指令创建react项目

    npx create-react-app react-basic(项目名称)
    

    创建成功以后,生成结果如下
    在这里插入图片描述

    (注意一个问题,使用脚手架创建react项目的时候,不允许使用驼峰命名法,只允许使用小写字母+连字符链接)

    创建成功后则会提示,并且产生一个命名好的文件夹,这就是所有的react文件的所在地点
    在这里插入图片描述

    接下来启动可以使用指令:

    yarn start    或者 npm start
    

等待大约30秒以后,出现这个web界面即为成功,这个时刻react服务会占据你的3000端口(默认)
在这里插入图片描述

react的项目资源

初始创建出来的react文件应该是这样子的
在这里插入图片描述

其中,入口文件为index.js,内部结构如下,和vue中挂载的原理很接近

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';                        
import reportWebVitals from './reportWebVitals';
//获取跟组件dom元素,并且根据这个元素创建节点
const root = ReactDOM.createRoot(document.getElementById('root'));
//然后把渲染挂载到这个dom节点上
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

  • react为框架的核心包
  • reactdom是专门做渲染的包
  • App是根组件
  • index.css是全局的框架

另外去掉严格模式节点: 18以后简易这样子处理会好一些
在这里插入图片描述

  • 另外注意,linux下安装react是一样的逻辑和处理方法,难能可贵的一点

jsx

jsx是个啥

jsx就是JavaScriptHTML,在js中去书写html标签,文件名后缀可以是js文件,也可以是jsx文件

//举个例子
function App() {
  return (
    <div className="App"/>
  );
}

优势:语法类似html,可以使用js的可编程性创建html,综合了以上两种的优点

注意:jsx是js语法的扩展,本身浏览器是不理解jsx语法的,在底层中react中有一个jsx的包帮助转化成js语法

jsx的具体语法

一些使用的案例

注意这些案例只是一些实际应用到jsx的情况,不是什么官方语法!可以简单学着写一写,理解为主

和模板语法很像 大致写法就是 {js的表达式} ,注意这里是表达式!

表达式:说白了表达式的意思就是数值,最简单的判断方法就是看能不能输出到控制台
在这里插入图片描述

列表渲染

比如我们想要实现一个数组的时候,可以通过map在遍历过程中创建标签,举个例子差不多是这样的

在这里插入图片描述

总结起来就是在js中写html自由度较高,但是想在html标签中写js表达式,要在中括号里写

并且这个规律是可以嵌套的

如何判断是不是表达式:能return,或者说能打印的

另外在jsx语法中,可以作为数值的东西,包括html标签捏

条件渲染

或者说选择性渲染,可以使用三元运算符和逻辑运算符,或者像这样手写if

例如这个列表中,我们对于id大于15的人进行显示

在这里插入图片描述

总之就是在html标签内部写js表达式的时候要加上{}

或者说满足另一个需求,符合条件才渲染(这个时候想要显示的html标签可以使用null来代替)

在这里插入图片描述

对于一些比较复杂,而且方向比较多的分支,建议将其抽象出来作为一个方法

在这里插入图片描述
在实际应用中,为了防止某些标签发生响应不及时,或者无法动态更新自己的属性的时候,我们还有一种肥肠丑陋但是有效的写法

{ isShow && <div>利用前面的布尔数值来判断这个是否显示</div>}

css样式处理

使用jsp语法可以对style实现样式的处理…不过这个玩意好像在js里也是有的

样式一共有两种控制方法:内联控制,以及第二种使用类名控制

在这里插入图片描述

很简单,并且第一种的第一个{}内部可以换成一个符合style规范的对象

另外类名可以动态控制,也可以有多个

注意事项

  • jsx必须存在一个根节点,可以使用<></>(幽灵节点替代)

在这里插入图片描述

是不被允许的,必须有一个总领的标签元素

  • jsx支持换行,如果换行最好使用()进行包裹,这样子代码可读性会更好一些

组件

组件是什么

组件化开发在vue中也是经常使用的,每个组件都是独立的,并且组件之间也可以进行通信,有利于复用和维护.

组件的两种类型以及渲染

  • 函数组件
  • 类组件

函数组件的创建和渲染

函数类组件的创建其实就是一个函数,返回值为一个div标签

function Hello(){
    return <div>hello</div>
}

函数式组件的使用也是直接在父组件中使用

function App() {
  return (
    <div>   <Hello/>   </div>
  );}
  • 函数组件的要求是名称必须大写,不仅仅是语言规范,react内部也是通过标签的首字母判断这是html标签还是组件

类组件的创建和渲染

类组件的创建比较模板化,首先是继承react.component,然后是render必须有返回值

class HelloComponent extends React.Component{
    render(){
        return <div>hello this is a classComponent</div>
    }
}
  • 和函数组件一样,类组件名称首字母要大写
  • 继承自React.Component类
  • 要导入对应的包"React"

事件绑定

  • 如何绑定事件

on+(对应的事件) = {触发的函数}

以下是一个比较标准的类组件中绑定事件的写法

class HelloComponent extends React.Component{
    f1=()=>{
        console.log("回调函数已经启动")
    }
    render(){
        return <div onClick={this.f1}>hello this is a classComponent</div>
    }
}
  • 事件对象

想要获取事件对象本身,例如在上面这个地方获取到"点击事件"的具体信息

只需要在事件绑定的回调函数里面,加上参数e

   f1=( e )=>{
        console.log("事件的具体信息为",e)
    }
    render(){
        return <div onClick={this.f1}>hello this is a classComponent</div>
    }

按照上面的例子修改,则事件具体信息如下

在这里插入图片描述

得到事件以后,我们可以进行一些操作**:比如阻止默认跳转,阻止冒泡,懒加载等等**

  • 事件绑定的函数传入额外参数

有些时候想要传入的是参数,或者说想要传入事件和参数两种argument,就用回调函数先把参数是一个事件这种事情,确定下来

    f1=(e,num)=>{
        console.log("事件为:",e,"传入的参数为",num)
    }
    render(){
        return <div onClick={(e)=>this.f1(e,12)}>hello this is a classComponent</div>
    }
/*解释一下为什么这样子写
首先是使用回调函数的形式,是为了第一步先行接收事件对象,后面即使在传入参数的时候,也不会把这个当成普通参数看待
如果是一开始就一同接收,只会当成一个普通的参数*/ 

组件状态(类组件为主)

  • 状态的定义

状态的定义其实很简单,就是一个在类组件中,名为state的对象
在这里插入图片描述
在vue里面,我们可以对某个固定属性绑定v-model标签,这个标签可以让data和数据产生双向的响应的动态绑定.并且vue本身主打就是响应式.但是react有所不同,react的响应式效果没有vue那么强大,但是更加专一.
写在状态中的数据,是可以被响应式检测和监听的

在这个state中定义的所有属性,都是一个状态,其实这部分很类似vue中的data

  • 组件的修改

组件内部数据的修改用到的方法比较粗暴,不允许我们直接去this.state.name=''xxxxx’这样修改

但是我们可以修改整个state(锁喉)

在这里插入图片描述

使用整个setState(对象)函数,在参数中填写一个新的state对象

(不然你以为它为什么叫setState…)

* 一些需要注意的问题
1.编写组件其实就是编写一个原生类/函数,定义状态必须使用state整个固定名称
2.修改state中的任何属性都不能通过直接赋值,只能通过setState方法,这个方法来自于继承

3.以及一些关于this的问题
//对象调用自己的方法,this就是当前的对象
//单独的全局函数调用,指向的是undefined(前提是严格模式,非严格模式(sloppy)下为自身)
//箭头函数没有自己的this,指向的是父上下文的this
//作为监听器的回调函数,指向的是监听的dom元素

4.一个老版本问题
以前的话,如果调用函数的时候不加上括号(),会让函数无法获取绑定到this属性
但是es6版本后更新了这个毛病,使用箭头函数可以自动绑定this

一些修改的小技巧:解构语法

用react做表单处理

目标:使用受控组件获取表单的数值

方法:受控组件,非受控组件

  • 受控组件:举个例子,input框自己的属性被react的状态控制

手动实现类似v-model双向数据绑定的操作

<input className={'inputLog'} onInput={
                    ()=>{//react中没有类似的语法糖,只能手动实现
                        const  str=document.querySelector('.inputLog').value
                        this.setState({
                            name:this.state.name,
                            valueOfBlock:str
                        })
                    } }/>

这种是稍微原始一点的操作(一看就是刚学完es6)

首先获取到当前dom元素的value数值,然后根据这个value数值修改状态(这也是v-model的使用方法)

  • 至于受控组件

则是数值不被state所控制,直接通过dom元素进行控制

组件之间通信

组件之间的通信可以分为以下情况和处理方法,由于函数和类组件的不同,可能还有不同的处理方式

  • 父子通信
    • 父传子
    • 子传父
  • 兄弟通信
  • 其他通信

父子通信

父传子通信

父亲向子元素传递数据的方法和vue有些相似,但是原理8一样

  • 父组件要传递的元素写在自己的state状态中
  • 子组件接收数据,在自己的标签中用自定义名称接收
  • 子组件使用数据的时候分两种情况
    • 子组件为函数类组件的时候,需要在函数声明加上一个参数,这样会传入一个对象,对象内部就包含了父组件传递的数据(用的是自己定义的名称)
    • 子组件为类组件的时候,可以在子组件内部直接使用this.props.xxx

class Father extends React.Component{ 
    state={   name:'this is father`s data'  }        父组件数据
    render() {
        return (<div>                                父组件中调用子组件
            <SonOfClass msg={this.state.name}/>      
            <SonOfFunction  msg={this.state.name}/>
        </div>)
    }
}
class SonOfClass extends React.Component{             类子组件
    render() {
        return (<div>
            类组件接收数据的方法为{this.props.msg}        类子组件接收
        </div>)
    }
}
function SonOfFunction(props) {                        函数子组件
    return (
        <div>
           函数组件接收数据的方法为{props.msg}            函数子组件接收(注意上面还有个函数)
        </div>
    )
}
子传父通信

子传父通信的原理为:子组件调用父组件传递过来的函数,并且把想要传递的数据当成函数的实参传入

父组件仍然是通过给子组件上标签的方法,给子组件传递一个函数对象

//父组件中的情况
    met1=(num)=>{
       console.log('子组件传递过来的消息为',num)//打印所有的方法
    }
    render() {
        return (<div>
            <SonOfClass method1={this.met1}/>//传入方法仍然是可以自定义名称的
        </div>)
    }

子组件可能会遇到一些问题,下面直接给出两种常用写法,再说为什么要这样

        <div>
            <button onClick={props.method1.bind(this,"数据")}>ddd</button>
            <button onClick={ () => props.method1("数据") }>ddd2</button>
        </div>

子组件调用的时候传入一些数据,然后父组件中就可以利用`这些数据修改点东西了

这里解释这两个button为什么要这样子写,因为我们要传入参数,对一个函数传入参数这种表达已经不符合"js表达式"

我们只有让返回值是一个传入参数的函数

  • 第一种就是bind,众所周知,bind的作用在原生js中是绑定上下文对象,并且返回一个新的函数
  • 第二种是使用箭头函数,返回值进行处理

兄弟通信

兄弟组件的通信,综合了以上两种方式,使用一个通过的父组件

A传递到Father组件,然后再由Father组件传递给B

这里不加解释了

其他通信

不是兄弟也不是父子的时候,通信方式就很抽象了

其实也不是很抽象,用到Provider和Consumer两个对象,这两个对象是在Context对象下的

  • 第一步,先创建Context,然后从里面得到两个对象Provider和Consumer

    (为了省点力气,这里我们直接使用解构语法)

在这里插入图片描述

(注意这里的defaultValue是默认数值,没啥影响)

通过解构语法直接得到传输对象

  • 第二步,用****包裹父组件的根组件,然后在value属性中,写下自己想要传输的数据

在这里插入图片描述

  • 第三步,在想要用到数据的地方,按照如下方法(固定格式),使进行传输数据

在这里插入图片描述

(注意Consumer不用包裹任何东西, 按照这个,里面写个jsx语法包裹回调函数就行力

这种传递数据的方法其实是父传子的延申,爷传孙罢

组件生命周期

首先注意,只有类组件由生命周期这个东西,虽然函数组件也存在更新和副作用的机制,但是本质上还是不一样的

组件的声明周期一共包括几个概念:

  • 三个阶段:挂载/创建,更新,卸载
  • 五个常用钩子函数
  • 两个阶段:render commit

有一张图画的挺清晰明白的(模仿着画的)

在这里插入图片描述

每个阶段都是由上至下进行经历的,在此期间会触发钩子函数方便访问

挂载阶段:
constructor:创建组件的时候最先执行,初始化state,创建ref,使用bind绑定什么的
(但是前两种是过时写法了,现在不怎么用)
render:每次组件渲染(包括初次创建和每次更新)都会触发,负责渲染ui(这里不能用this)
componentDidMount:组件挂载并且完成渲染以后执行一次,这时候可以进行一些网络请求和dom操作
更新阶段
render:同上
componentDidUpdate:更新结束触发,可以直接获取dom元素
卸载阶段
componentWillUnMount:8用解释了吧

注意两点:

  • render阶段是创建+渲染,在这个阶段是不允许我们调用this这个指向的
  • 另外在render和componentDidUpdate中,都不能使用setState这种更新函数,因为更新会造成这些钩子的死循环调用

钩子函数的使用方法举例:

class Life extends React.Component{
    constructor() {
       super();
       console.log("construct")
    }
    componentDidMount() {
        console.log("挂载结束")
    }
    render() {
        return (
            <div>
            </div>
        )
    }
}

关于hook

hook的本质也是一系列钩子函数,这些工资函数让函数组件也拥有了state

hook这个i能在函数组件中使用,解决了复用和class过于笨重的问题

  • 常用函数:useState

该钩子函数的返回值为一个数组,数组的第一项和第二项,分别为数据和修改数据的方法

该函数输入参数为这个数据的初始数值

每次使用这个函数,都可以得到一个数据和对应的方法,允许多次调用获得多个state属性

const [count,setCount]=useState(0)     //直接使用解构语法获得前面两项
//count:数据状态
//setCount(新数据):整体修改数据

这其中,setCount的本质和前面类组件的setState原理是一样的,都是用新数值替换旧数值,所以在需要一些复杂逻辑的时候,可以这样子写

//对于setCount(姑且这么称呼)这种函数,有一种情况为用回调函数作为参数
  setCount( ()=>{
     //编写运算逻辑.........
     return   //但是最后还是要返回东西
  })
//这样子帮助我们解决了一些复杂问题,其实本质还没变....

关于具体的使用

function TestHook_useStated(){
    //每一个state属性都要重新创建
    const [count,setCount]=useState(0)
    const [count2,setCount2]=useState(100)
    const [count3,setCount3]=useState({age:12,name:'张三'})
    //得到的修改数值的函数,参数就是新的state,本质和setState一样,用新数替换旧数值
    return (
        <>
            <div onClick={()=>setCount(count+1)}>{count}</div>
            <div onClick={()=>setCount2(count2-1)}>{count2}</div>
            <div onClick={()=>setCount3({age:count3.age+1,name:'李四'})}>{count3.age},{count3.name}</div>
        </>
   )
}
  • 常用函数useEffect

首先,有必要说明一下,什么是副作用

副作用:对于react来说,主作用就是根据内部数据渲染ui,除了主作用,剩下都是副作用,

比如dom操作,发送ajax请求,以及一些webapi的调用
useEffect就是干这个用的,把副作用放进这里面,维护函数的纯净

  • useEffect函数的执行时机是可以控制的,在默认条件下,执行是发生在任何一次更新(包括构建)

    //但是可以通过依赖项目,控制时机
    //useEffect有两个参数,一个参数为回调函数,另一个参数为监听数组
    //1.默认情况下不加整个参数,则每次更新/重构都会执行     useEffect(()=>{})
    //2.空数组,代表只执行一次                          useEffect(()=>{},[])
    //3,数组中的监听元素如果发生变化,则执行一次+初始化一次  useEffect(()=>{},[A,B,C])
    
  • useEffect对于一些副作用来说,是要进行消除的,函数内部提供了析构的方法,就是返回一个回调函数

    useEffect(()=>{
        return ()=>{
            //关于清理的逻辑
        }
    },[]) //这种就是只有初始化的时候执行一次的情况
    
  • 关于具体的使用案例如下

    function TestHook_useEffect(){
        useEffect(()=>{
            console.log("修改")
            document.querySelector('title').innerHTML=1;
            return ()=>{
                //关于清理的逻辑
            }
        },[]) //这种就是只有初始化的时候执行一次的情况
        return(
            <div onClick={()=>console.log("修改")}>
               点我测试
            </div>
        )
    }
    

路由

首先路由不是原生react中的内容,和vuex,redux一样,需要另外单独安装
(另外注意,v6版本是router的一个分水岭,我这里写的都是基于router6的内容)

下载指令为

yarn add react-router-dom@6

然后导入几个最重要的包

import {BrowserRouter, Link, Routes, Route} from 'react-router-dom'

就可以放心使用了

路由的核心组件

路由最重要的组件为四个

  • Router(分为哈希式路由HashRouter和浏览器路由BrowersRouter)
  • Link
  • Routes
  • Route

Router:最根本的展示区域,所有和路由相关的东西都应该包裹在内部

Link: 跳转路由的位置,需要在内部的to属性中写明将要跳转的地址,会在最后的h5界面中被变化为a标签

Routes:这个名字怪怪的,叫RouteContainer更好一些…

Route:路由组件,里面的path属性为开放端口,element属性则为具体的组件

路由会根据条件,从中跳转到合适的路由组件并且显示

举个例子:

                <BrowserRouter>
                    <Link to='/page/10'>首页</Link>
                    <Link to='/about/?id=10'>关于</Link>
                    <Routes>
                        <Route path='/page/:id' element={<Page/>}/>
                        <Route path='/about' element={<About/>}/>
                    </Routes>
                </BrowserRouter>

路由之间传递参数

路由传递参数有两种格式

  • 第一种,使用Params传递

    在父组件中,url中给传递数据的格式为如下格式

    to中直接传递参数,path中使用占位符的方式获取参数

     <Link to='/page/10'>首页</Link>
    
     <Route path='/page/:id' element={<Page/>}/>
    

​ 子组件中,使用useParams获取一个对象

     ```
      const params=useParams()
         return(
             <div>
                 输出结果为:{params.id}
             </div>
         )
     ```
  • 第二种,使用SearchParams传递

    在父组件中,url中给传递数据的格式为如下格式

    to中通过url的get格式传递参数

     <Link to='/page/?id=10'>首页</Link>
    

​ 子组件中,使用useParams获取一个数组,数组的第一个是一个解构类似map的对象

const [params]=useSearchParams()
    return(
        <div>
            输出结果为:{params.get("id")}
        </div>
    )

至于嵌套路由,这里直接举个例子

import { BrowserRouter as Router, Link, Route } from 'react-router-dom';

function ParentComponent() {
  return (
    <div>
      <h1>父级组件内容</h1>
          <li><Link to="/parent/child1">子路由1</Link></li>
          <li><Link to="/parent/child2">子路由2</Link></li>
      {/* 子级路由规则 */}
      <Route path="/parent/child1" component={ChildComponent1} />
      <Route path="/parent/child2" component={ChildComponent2} />
    </div>
  );
}

function ChildComponent1() {
  return <h2>子组件1内容</h2>;
}

function ChildComponent2() {
  return <h2>子组件2内容</h2>;
}

function App() {
  return (
    <Router>
      {/* 路由规则和组件的对应关系 */}
      <Route path="/parent" component={ParentComponent} />
    </Router>
  );
}

编程式导航

编程式导航,其实就是我们尝试使用代码逻辑去控制路由的跳转,而不是link

使用编程导航,主要一下两步骤

  1. 通过useNavigate获取一个跳转函数
  2. 调用跳转函数,输入路由和其他依赖作为参数,完成路由跳转

举个例子

    const navigage=useNavigate()
    const goPage=function (){
        navigage('/page',{replace:true})
    }
    return(
        <div>
            <button onClick={goPage}>跳到首页</button>
        </div>
    )
//跳转函数里面自带两个参数
//里面两个参数,第一个参数要跳转到的路由地址
//第二个参数为一些配置信息的对象,比如replace:true 为不加入历史路径
//注意以上实现只能在<Router>组件中使用,换句话说就是在这个标签里面(就是哪两种核心组件)
//所以一般引入一个新的组件,比如routerLink(自己随便去起个名字吧)用来管理固有的信息和逻辑
//{最好在根组件外部创建}

#补充:关于状态管理工具

React笔记2

redux:集中状态管理,类似Java中的vuex

redux

redux的本体其实是一个状态管理工具,js的状态容器,在react中,通常用来存储一些通用的,需要响应化的属性

npm install --save redux

绑定react

npm install --save react-redux

创建开发者工具

store是根据reducer方法创建的

集中状态管理最终抽象一下可以理解为这样子

  • 修改状态的方法:store发送action对象
  • 获得状态的方法:store.getState()函数即可得到state对象

在这里插入图片描述

react-redux

redux本身支持很多东西,包括原生js,redux官方出品,专门用于react的绑定库,方便一些操作

  • porvider:让store能全局化
  • connect:让组件和store进行关联

基本使用

Provider:

包裹在根组件上(注意一定是根组件上),并且在这里往下传递一个store属性,让下面都能访问到store

const store=react.createStore()
root.render(
    <Provider store={store}>
        <App />
        <TestRouter></TestRouter>
    </Provider>
);

这样传递一个很显著的特点是,后面的组件都不需要再手动调用store来进行dispatch或者和getState

并且结合后面的两个方法,可以让发送action的方法,和state都整合进props里面

connect的参数:

mapStateToProps(state,ownProps),监听store是否被修改,并且把store中的state绑定到props中

mapDispatchToProps(dispatch,ownProps),把action绑定到props中

(上面两个函数的第二个参数可以不用写,因为把你需要的东西加入返回值里面,就会自动绑定到你的props中)

  • mapDispatchToProps:作用是将Action的构建方法以返回值的形式封装进props中,举个例子,主要用在发出修改的主页上面

    //使用了这个绑定该方法以后,就会把你需要的东西绑定进props中
    const misDispatchToProps=(dispatch)=>{
        return{
            sentAct:()=>{                     发送action对象的方法
                dispatch({                    由于在根组件上已经提供了一个store,所以这里直接可以使用dispatch
                    type:'send',
                    value:a
                })
                a++
            }
        }
    }
    //首页组件
    class ComA extends React.Component{
        handleClick=()=>{
            //发送action
            this.props.sentAct();
        }
       render(){
           return(
               <div>
                   <button onClick={()=>{this.handleClick()}}> + </button>
               </div>
           )
       }
    }
    
    //增强这个对象
    export default connect(null,misDispatchToProps)(ComA)
    
  • mapStateToProps:**作用是将Store中更新的state接受下来,**并且以返回值的形式保存在props中,主要用在接收组件上面

    //会把接收到的,被修改以后的state保存在props中
    const mapStateToProps=(state)=>{
        console.log('comb',state)
        return state
    }
    
    //首页组件
    class Comb extends React.Component{
        sta=this.props
        render() {
            return(
                <div>
                    显示数据{this.props.value}
                </div>
            )
        }
    }
    
    //增强这个对象
    export default connect(mapStateToProps,null)(Comb)
    

大致的逻辑结构可以为:

在这里插入图片描述

某种角度上来说,可以认为props托管了一部分本该有state发出的动作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/904712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.Jetson Orin Nano Developer Kit系统刷机

本教程有3种方法刷机&#xff0c;根据需要自己选择适合自己的方案。 一:使用>32G的SD卡安装开发套件; 二:在Ubuntu18.04下通过SDK Manager软件在线安装系统. 三:在Ubuntu18.04下通过脚本方式安装系统. 注意&#xff1a;Ubuntu的账号不能为一些常见的包名如&#xff1a;p…

【学习日记】【FreeRTOS】FreeRTOS 移植到 STM32F103C8

前言 本文基于野火 FreeRTOS 教程&#xff0c;内容是关于 FreeRTOS 官方代码的移植的注意事项&#xff0c;并将野火例程中 STM32F103RC 代码移植到 STM32F103C8。 一、FreeRTOS V9.0.0 源码的获取 两个下载链接&#xff1a; 官 网 代码托管 二、源码文件夹内容简介 Source…

Docker(一)-安装、架构、业务开发常用命令、Dockerile、镜像卷、镜像仓库

基于业务开发使用Docker Docker是一个开源的容器引擎&#xff0c;它有助于更快地交付应用。Docker可将应用程序和基础设施层隔离&#xff0c;并且能将基础设施当作程序一样进行管理。使用 Docker可更快地打包、测试以及部署应用程序&#xff0c;并可以缩短从编写到部署运行代码…

为什么需要单元测试?

为什么需要单元测试&#xff1f; 从产品角度而言&#xff0c;常规的功能测试、系统测试都是站在产品局部或全局功能进行测试&#xff0c;能够很好地与用户的需要相结合&#xff0c;但是缺乏了对产品研发细节&#xff08;特别是代码细节的理解&#xff09;。 从测试人员角度而言…

Springboot 实践(10)spring cloud 与consul配置运用之服务的注册与发现

前文讲解&#xff0c;完成了springboot、spring security、Oauth2.0的继承&#xff0c;实现了对系统资源的安全授权、允许获得授权的用户访问&#xff0c;也就是实现了单一系统的全部技术开发内容。 Springboot是微服务框架&#xff0c;单一系统只能完成指定系统的功能&#xf…

【简单认识Docker网络管理】

文章目录 一、Docker 网络实现原理二、Docker 的网络模式1.四种网络模式2.各网络模式详解&#xff08;1&#xff09;Host模式&#xff08;2&#xff09;Container模式&#xff08;3&#xff09;None模式&#xff08;4&#xff09;Bridge模式 3.指定容器网络模式4.自定义网络模式…

web文件上传

文件上传指的是&#xff0c;将本地的图片、视频、音频上传到服务器&#xff0c;提供给其他用户浏览和下载的过程 前端需求 想要进行文件上传对于web前端来说有三个重要要素 1.<input type"file" name"image"> 提供这样的file文件上传格式 2. metho…

【Unity】自带的录屏插件Recorder

目录 Recorder简介Recorder导入Recorder使用 Recorder简介 Recorder是Unity官方的录屏插件&#xff0c;可以直接录制Game窗口&#xff0c;还可以录制不同相机的视图。不仅可以直接生成视频、帧动画图、还可以制作gif和animation。 Recorder导入 菜单栏Windows→Package Mana…

VINS-Mono中的边缘化与滑窗 (4)——VINS边缘化为何是局部变量边缘化?

文章目录 0.前言1.系统构建1.1.仿真模型1.2.第一次滑窗优化1.3.第二次全局优化 2.边缘化时不同的舒尔补方式2.1.边缘化时舒尔补的意义2.2.不同的边缘化方式 3.边缘化时不同的舒尔补方式实验验证3.1.全局schur的操作方式3.2.VIO或VINS中局部边缘化的方式3.3.两种方式和全局优化方…

【Linux】文件的描述符和重定向

文件的描述符和重定向 C语言的文件读写操作代码 open系统打开文件方法系统读写文件操作文件描述符文件重定向怎么理解文件缓冲区 C语言的文件读写操作 文件写入 fputs int fputs(const char *s, FILE *stream); s&#xff1a;要写入的字符串 stream&#xff1a;要写入对应的目标…

halcon库文件封装操作方法介绍

头文件写法参考 getarea.h 导出函数设定&#xff1a; extern “C” __declspec(dllexport) void _stdcall cpp文件写法参看 3.vs 库文件配置介绍 头文件及包含的库文件目录设定 &#xff08;1&#xff09;头文件设定E:\halcon\env\opencv\include\opencv2;E:\halcon\env\ope…

接口限流注解 RateLimiter (现成直接用)

1. 限流注解 import com.ruoyi.common.constant.Constants; import com.ruoyi.common.enums.LimitType;import java.lang.annotation.*;/*** 限流注解* */ Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) Documented public interface RateLimiter {/*** 限流…

DSO 系列文章(3)——DSO后端正规方程构造与Schur消元

文章目录 DSO代码注释&#xff1a;https://github.com/Cc19245/DSO-CC_Comments

javascript期末作业【三维房屋设计】 【文末源码+文档下载】

1、引入three.js库 官网下载three.js 库 放置目录并引用 引入js文件: 设置场景&#xff08;scene&#xff09; &#xff08;1&#xff09;创建场景对象 &#xff08;2&#xff09;设置透明相机 1,透明相机的优点 透明相机机制更符合于人的视角,在场景预览和游戏场景多有使用…

安装docker配置镜像加速器,容器等

1.安装docker服务&#xff0c;配置镜像加速器 2.下载系统镜像&#xff08;Ubuntu、 centos&#xff09; 3.基于下载的镜像创建两个容器 &#xff08;容器名一个为自己名字全拼&#xff0c;一个为首名字字母&#xff09; 4.容器的启动、 停止及重启操作 5.怎么查看正在运行的容器…

快速排序 | C++|时间空间复杂度

1.概念 快速排序(QuickSort)的基本思想是:通过一趟排序将待排记录分割成独立的两部分&#xff0c;其中一部分记录的关键字均比另一部分记录的关键字小&#xff0c;则可分别对这两部分记录继续进行排序&#xff0c;以达到整个序列有序的目的。 2.算法思想描述 1.进行一次划分&…

在线HmacMd5加密工具--在线获取哈希值又称摘要

具体请前往&#xff1a;在线计算HMacMd5工具

STL vector基本用法

目录 vector介绍vector的使用vector的定义vector接口函数构造函数和赋值重载迭代器元素访问vector容量相关函数vector增加 删除 修改操作关系操作符 vector介绍 vector是可变大小数组的序列容器。像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可…

Dockers搭建个人网盘、私有仓库,Dockerfile制作Nginx、Lamp镜像

目录 1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 &#xff08;1&#xff09;下载mysql:5.6和owncloud镜像 &#xff08;2&#xff09;创建启动mysql:5.6和owncloud容器 &#xff08;3&#xff09;在浏览器中输入网盘服务器的IP地址&#xff0c;进行账…

stm32单片机/51单片机蜂鸣器不响(proteus模拟)

蜂鸣器不发生原因就1个&#xff1a;电压不够 所以需要提高蜂鸣器2端的电压&#xff1a;可以采用的方法有&#xff1a; 1提高蜂鸣器电阻&#xff0c;这样根据分压原理&#xff0c;可以提升蜂鸣器2段电压 2更改蜂鸣器的工作电压为更小的值&#xff0c;这个可以通过在proteus内…