详解React 代码共享最佳实践方式

任何一个项目发展到一定复杂性的时候,必然会面临逻辑复用的问题。在React中实现逻辑复用通常有以下几种方式:Mixin高阶组件(HOC)修饰器(decorator)Render PropsHook。本文主要就以上几种方式的优缺点作分析,帮助开发者针对业务场景作出更适合的方式。

Mixin

这或许是刚从Vue转向React的开发者第一个能够想到的方法。Mixin一直被广泛用于各种面向对象的语言中,其作用是为单继承语言创造一种类似多重继承的效果。虽然现在React已将其放弃中,但Mixin的确曾是React实现代码共享的一种设计模式。

广义的 mixin 方法,就是用赋值的方式将 mixin 对象中的方法都挂载到原对象上,来实现对象的混入,类似 ES6 中的 Object.assign()的作用。原理如下:

const mixin = function (obj, mixins) {
  const newObj = obj
  newObj.prototype = Object.create(obj.prototype)

  for (let prop in mixins) {
    // 遍历mixins的属性
    if (mixins.hasOwnPrototype(prop)) {
      // 判断是否为mixin的自身属性
      newObj.prototype[prop] = mixins[prop]; // 赋值
    }
  }
  return newObj
};

在 React 中使用 Mixin

假设在我们的项目中,多个组件都需要设置默认的name属性,使用mixin可以使我们不必在不同的组件里写多个同样的getDefaultProps方法,我们可以定义一个mixin

const DefaultNameMixin = {
  getDefaultProps: function () {
    return {
      name: "Joy"
    }
  }
}

为了使用mixin,需要在组件中加入mixins属性,然后把我们写好的mixin包裹成一个数组,将它作为mixins的属性值:

const ComponentOne = React.createClass({
  mixins: [DefaultNameMixin]
  render: function () {
    return <h2>Hello {this.props.name}</h2>
  }
})

写好的mixin可以在其他组件里重复使用。

由于mixins属性值是一个数组,意味着我们可以同一个组件里调用多个mixin。在上述例子中稍作更改得到:

const DefaultFriendMixin = {
  getDefaultProps: function () {
    return {
      friend: "Yummy"
    }
  }
}

const ComponentOne = React.createClass({
  mixins: [DefaultNameMixin, DefaultFriendMixin]
  render: function () {
    return (
      <div>
        <h2>Hello {this.props.name}</h2>
        <h2>This is my friend {this.props.friend}</h2>
      </div>
    )
  }
})

我们甚至可以在一个mixin里包含其他的mixin

比如写一个新的mixin``DefaultProps包含以上的DefaultNameMixinDefaultFriendMixin

const DefaultPropsMixin = {
  mixins: [DefaultNameMixin, DefaultFriendMixin]
}

const ComponentOne = React.createClass({
  mixins: [DefaultPropsMixin]
  render: function () {
    return (
      <div>
        <h2>Hello {this.props.name}</h2>
        <h2>This is my friend {this.props.friend}</h2>
      </div>
    )
  }
})

至此,我们可以总结出mixin至少拥有以下优势:

  • 可以在多个组件里使用相同的mixin
  • 可以在同一个组件里使用多个mixin
  • 可以在同一个mixin里嵌套多个mixin

但是在不同场景下,优势也可能变成劣势:

  • 破坏原有组件的封装,可能需要去维护新的stateprops等状态;
  • 不同mixin里的命名不可知,非常容易发生冲突;
  • 可能产生递归调用问题,增加了项目复杂性和维护难度;

除此之外,mixin在状态冲突、方法冲突、多个生命周期方法的调用顺序等问题拥有自己的处理逻辑。感兴趣的同学可以参考一下以下文章:

React Mixin 的使用

Mixins Considered Harmful

高阶组件

由于mixin存在上述缺陷,故React剥离了mixin,改用高阶组件来取代它。

高阶组件本质上是一个函数,它接受一个组件作为参数,返回一个新的组件。

React官方在实现一些公共组件时,也用到了高阶组件,比如react-router中的withRouter,以及Redux中的connect。在这以withRouter为例。

默认情况下,必须是经过Route路由匹配渲染的组件才存在this.props、才拥有路由参数、才能使用函数式导航的写法执行this.props.history.push('/next')跳转到对应路由的页面。高阶组件中的withRouter作用是将一个没有被Route路由包裹的组件,包裹到Route里面,从而将react-router的三个对象historylocationmatch放入到该组件的props属性里,因此能实现函数式导航跳转

withRouter的实现原理:

const withRouter = (Component) => {
  const displayName = `withRouter(${Component.displayName || Component.name})`
  const C = props => {
    const { wrappedComponentRef, ...remainingProps } = props
    return (
      <RouterContext.Consumer>
        {context => {
          invariant(
            context,
            `You should not use <${displayName} /> outside a <Router>`
          );
          return (
            <Component
              {...remainingProps}
              {...context}
              ref={wrappedComponentRef}
            />
          )
        }}
      </RouterContext.Consumer>
    )
}

使用代码:

import React, { Component } from "react"
import { withRouter } from "react-router"
class TopHeader extends Component {
  render() {
    return (
      <div>
        导航栏
        {/* 点击跳转login */}
        <button onClick={this.exit}>退出</button>
      </div>
    )
  }

  exit = () => {
    // 经过withRouter高阶函数包裹,就可以使用this.props进行跳转操作
    this.props.history.push("/login")
  }
}
// 使用withRouter包裹组件,返回history,location等
export default withRouter(TopHeader)

由于高阶组件的本质是获取组件并且返回新组件的方法,所以理论上它也可以像mixin一样实现多重嵌套。

例如:

写一个赋能唱歌的高阶函数

import React, { Component } from 'react'

const widthSinging = WrappedComponent => {
	return class HOC extends Component {
		constructor () {
			super(...arguments)
			this.singing = this.singing.bind(this)
		}

		singing = () => {
			console.log('i am singing!')
		}

		render() {
			return <WrappedComponent />
		}
	}
}

写一个赋能跳舞的高阶函数

import React, { Component } from 'react'

const widthDancing = WrappedComponent => {
	return class HOC extends Component {
		constructor () {
			super(...arguments)
			this.dancing = this.dancing.bind(this)
		}

		dancing = () => {
			console.log('i am dancing!')
		}

		render() {
			return <WrappedComponent />
		}
	}
}

使用以上高阶组件

import React, { Component } from "react"
import { widthSing, widthDancing } from "hocs"

class Joy extends Component {
  render() {
    return <div>Joy</div>
  }
}

// 给Joy赋能唱歌和跳舞的特长
export default widthSinging(withDancing(Joy))

由上可见,只需使用高阶函数进行简单的包裹,就可以把原本单纯的 Joy 变成一个既能唱歌又能跳舞的夜店小王子了!

使用 HOC 的约定

  • 在使用HOC的时候,有一些墨守成规的约定:
  • 将不相关的 Props 传递给包装组件(传递与其具体内容无关的 props);
  • 分步组合(避免不同形式的 HOC 串联调用);
  • 包含显示的 displayName 方便调试(每个 HOC 都应该符合规则的显示名称);
  • 不要在render函数中使用高阶组件(每次 render,高阶都返回新组件,影响 diff 性能);
  • 静态方法必须被拷贝(经过高阶返回的新组件,并不会包含原始组件的静态方法);
  • 避免使用 ref(ref 不会被传递);

HOC 的优缺点

至此我们可以总结一下高阶组件(HOC)的优点:

  • HOC是一个纯函数,便于使用和维护;
  • 同样由于HOC是一个纯函数,支持传入多个参数,增强其适用范围;
  • HOC返回的是一个组件,可组合嵌套,灵活性强;

当然HOC也会存在一些问题:

  • 当多个HOC嵌套使用时,无法直接判断子组件的props是从哪个HOC负责传递的;
  • 当父子组件有同名props,会导致父组件覆盖子组件同名props的问题,且react不会报错,开发者感知性低;
  • 每一个HOC都返回一个新组件,从而产生了很多无用组件,同时加深了组件层级,不便于排查问题;

修饰器高阶组件属于同一模式,在此不展开讨论。

Render Props

Render Props是一种非常灵活复用性非常高的模式,它可以把特定行为或功能封装成一个组件,提供给其他组件使用让其他组件拥有这样的能力。

The term “render prop” refers to a technique for sharing code between React components using a prop whose value is a function.

这是React官方对于Render Props的定义,翻译成大白话即:“Render Props是实现React Components之间代码共享的一种技术,组件的props里边包含有一个function类型的属性,组件可以调用该props属性来实现组件内部渲染逻辑”。

官方示例:

<DataProvider render={(data) => <h1>Hello {data.target}</h1>} />

如上,DataProvider组件拥有一个叫做render(也可以叫做其他名字)的props属性,该属性是一个函数,并且这个函数返回了一个React Element,在组件内部通过调用该函数来完成渲染,那么这个组件就用到了render props技术。

读者或许会疑惑,“我们为什么需要调用props属性来实现组件内部渲染,而不直接在组件内完成渲染”?借用React官方的答复,render props并非每个React开发者需要去掌握的技能,甚至你或许永远都不会用到这个方法,但它的存在的确为开发者在思考组件代码共享的问题时,提供了多一种选择。

Render Props使用场景

我们在项目开发中可能需要频繁的用到弹窗,弹窗 UI 可以千变万化,但是功能却是类似的,即打开关闭。以antd为例:

import { Modal, Button } from "antd"
class App extends React.Component {
  state = { visible: false }

  // 控制弹窗显示隐藏
  toggleModal = (visible) => {
    this.setState({ visible })
  };

  handleOk = (e) => {
    // 做点什么
    this.setState({ visible: false })
  }

  render() {
    const { visible } = this.state
    return (
      <div>
        <Button onClick={this.toggleModal.bind(this, true)}>Open</Button>
        <Modal
          title="Basic Modal"
          visible={visible}
          onOk={this.handleOk}
          onCancel={this.toggleModal.bind(this, false)}
        >
          <p>Some contents...</p>
        </Modal>
      </div>
    )
  }
}

以上是最简单的Model使用实例,即便是简单的使用,我们仍需要关注它的显示状态,实现它的切换方法。但是开发者其实只想关注与业务逻辑相关的onOk,理想的使用方式应该是这样的:

<MyModal>
  <Button>Open</Button>
  <Modal title="Basic Modal" onOk={this.handleOk}>
    <p>Some contents...</p>
  </Modal>
</MyModal>

可以通过render props实现以上使用方式:

import { Modal, Button } from "antd"
class MyModal extends React.Component {
  state = { on: false }

  toggle = () => {
    this.setState({
      on: !this.state.on
    })
  }

  renderButton = (props) => <Button {...props} onClick={this.toggle} />

  renderModal = ({ onOK, ...rest }) => (
    <Modal
      {...rest}
      visible={this.state.on}
      onOk={() => {
        onOK && onOK()
        this.toggle()
      }}
      onCancel={this.toggle}
    />
  )

  render() {
    return this.props.children({
      Button: this.renderButton,
      Modal: this.renderModal
    })
  }
}

这样我们就完成了一个具备状态和基础功能的Modal,我们在其他页面使用该Modal时,只需要关注特定的业务逻辑即可。

以上可以看出,render props是一个真正的React组件,而不是像HOC一样只是一个可以返回组件的函数,这也意味着使用render props不会像HOC一样产生组件层级嵌套的问题,也不用担心props命名冲突产生的覆盖问题。

render props使用限制

render props中应该避免使用箭头函数,因为这会造成性能影响。

比如:

// 不好的示例
class MouseTracker extends React.Component {
  render() {
    return (
      <Mouse render={mouse => (
        <Cat mouse={mouse} />
      )}/>
    )
  }
}

这样写是不好的,因为render方法是有可能多次渲染的,使用箭头函数,会导致每次渲染的时候,传入render的值都会不一样,而实际上并没有差别,这样会导致性能问题。

所以更好的写法应该是将传入render里的函数定义为实例方法,这样即便我们多次渲染,但是绑定的始终是同一个函数。

// 好的示例
class MouseTracker extends React.Component {
  renderCat(mouse) {
  	return <Cat mouse={mouse} />
  }

  render() {
    return (
		  <Mouse render={this.renderTheCat} />
    )
  }
}

render props的优缺点

优点

  • props 命名可修改,不存在相互覆盖;
  • 清楚 props 来源;
  • 不会出现组件多层嵌套;

缺点

  • 写法繁琐;
  • 无法在return语句外访问数据;
  • 容易产生函数回调嵌套;

如下代码:

const MyComponent = () => {
  return (
    <Mouse>
      {({ x, y }) => (
        <Page>
          {({ x: pageX, y: pageY }) => (
            <Connection>
              {({ api }) => {
                // yikes
              }}
            </Connection>
          )}
        </Page>
      )}
    </Mouse>
  )
}

Hook

React的核心是组件,因此,React一直致力于优化和完善声明组件的方式。从最早的类组件,再到函数组件,各有优缺点。类组件可以给我们提供一个完整的生命周期和状态(state),但是在写法上却十分笨重,而函数组件虽然写法非常简洁轻便,但其限制是必须是纯函数,不能包含状态,也不支持生命周期,因此类组件并不能取代函数组件

React团队觉得组件的最佳写法应该是函数,而不是类,由此产生了React Hooks

React Hooks 的设计目的,就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件。

为什么说类组件“笨重”,借用React官方的例子说明:

import React, { Component } from "react"

export default class Button extends Component {
  constructor() {
    super()
    this.state = { buttonText: "Click me, please" }
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    this.setState(() => {
      return { buttonText: "Thanks, been clicked!" }
    })
  }
  render() {
    const { buttonText } = this.state
    return <button onClick={this.handleClick}>{buttonText}</button>
  }
}

以上是一个简单的按钮组件,包含最基础的状态和点击方法,点击按钮后状态发生改变。

本是很简单的功能组件,但是却需要大量的代码去实现。由于函数组件不包含状态,所以我们并不能用函数组件来声明一个具备如上功能的组件。但是我们可以用Hook来实现:

import React, { useState } from "react"

export default function Button() {
  const [buttonText, setButtonText] = useState("Click me,   please")

  function handleClick() {
    return setButtonText("Thanks, been clicked!")
  }

  return <button onClick={handleClick}>{buttonText}</button>
}

相较而言,Hook显得更轻量,在贴近函数组件的同时,保留了自己的状态。

在上述例子中引入了第一个钩子useState(),除此之外,React官方还提供了useEffect()useContext()useReducer()等钩子。具体钩子及其用法详情请见官方

Hook的灵活之处还在于,除了官方提供的基础钩子之外,我们还可以利用这些基础钩子来封装和自定义钩子,从而实现更容易的代码复用。

Hook 优缺点

优点

  • 更容易复用代码;
  • 清爽的代码风格;
  • 代码量更少;

缺点

  • 状态不同步(函数独立运行,每个函数都有一份独立的作用域)
  • 需要更合理的使用useEffect
  • 颗粒度小,对于复杂逻辑需要抽象出很多hook

总结

除了Mixin因为自身的明显缺陷而稍显落后之外,对于高阶组件render propsreact hook而言,并没有哪种方式可称为最佳方案,它们都是优势与劣势并存的。哪怕是最为最热门的react hook,虽然每一个hook看起来都是那么的简短和清爽,但是在实际业务中,通常都是一个业务功能对应多个hook,这就意味着当业务改变时,需要去维护多个hook的变更,相对于维护一个class而言,心智负担或许要增加许多。只有切合自身业务的方式,才是最佳方案

参考文档:

React Mixin 的使用

Mixins Considered Harmful

Higher-Order Components

Render Props

React 拾遗:Render Props 及其使用场景

Hook 简介

到此这篇关于React 代码共享最佳实践方式的文章就介绍到这了,更多相关React 代码共享内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • react native基于FlatList下拉刷新上拉加载实现代码示例

    react native 的上拉加载一直困扰着自己,一直用的第三方组件,但是可维护性不高,而且也不太好用,最近工作没那么忙,就研究下了官方的FlatList,做出来的成果,比第三方组件流畅度高好多,而且也很好用 官方介绍:https://reactnative.cn/docs/flatlist/ 下面是效果图: ios效果图 android效果图 总体思路就是:就是计算屏幕高度,然后减去导航的头部,根据列表高度计算出每页的个数,然后向上取整.这样做的目的是:防止不满屏状态下的,onEndReac

  • react实现点击选中的li高亮的示例代码

    虽然只是一个简单的功能,还是记录一下比较好.页面上有很多个li,要实现点击到哪个就哪个高亮.当年用jq的时候,也挺简单的,就是选中的元素给addClass,然后它的兄弟元素removeClass,再写个active的样式就搞定了.那现在用react要实现类似的操作,我想到的就是用一个currentIndex,通过判断currentIndex在哪个元素实现切换. 先上一下效果图: 代码: class Category extends React.Component { constructor(pr

  • react写一个select组件的实现代码

    之前一直用的antd的Select组件,但在有些端并不适用,而原生的select样式修改不灵活,遂产生自己写一个组件的想法.观察select组件: <select onChange={(value) => {this.value=value}} <option value='1'>man</option> <option value='0'>woman</option> </select> 可以看出数据都是在option中,有值val

  • 在React 组件中使用Echarts的示例代码

    在完成一个需求的时候碰到一个场景需要使用柱状图.涉及到可视化,第一反应当然是Echarts了.平时用js加载Echarts组件很方便,但是在React中就要费下神了.各种连蒙带猜实现了.edmo里的 这里我们要在自己搭建的react项目中使用ECharts,我们可以在ECharts官网上看到有一种方式是在 webpack 中使用 ECharts,我们需要的就是这种方法. 我们在使用ECharts之前要先安装ECharts,在以往的开发模式中,我们很多使用就是把官网中的ECharts的核心js文件

  • React 条件渲染最佳实践小结(7种)

    在 React 中,条件渲染可以通过多种方式,不同的使用方式场景取决于不同的上下文. 在本文中,我们将讨论所有可用于为 React 中的条件渲染编写更好的代码的方法. 条件渲染在每种编程语言(包括 javascript)中都是的常见功能. 在 javascript 中,我们通常使用if else 语句,switch case语句和三元运算符编写条件渲染. 以上所有这些方法都适用于 React. 但是问题是,我们如何才能有效地使用它们? 像你知道的那样,React 具有 JSX 标记,通常我们需要

  • react-native 圆弧拖动进度条实现的示例代码

    本文介绍了react-native 圆弧拖动进度条实现的示例代码,分享给大家,具体如下: 先上效果图 因为需求需要实现这个效果图 非原生实现, 难点1:绘制 使用svg 难点2:点击事件的处理 难点3:封装 由于绘制需要是使用svg 此处自行百度 按照svg以及api 教学 视图代码块 render() { return ( <View pointerEvents={'box-only'} //事件处理 {...this._panResponder.panHandlers}> //实际圆环 {

  • 深入学习TypeScript 、React、 Redux和Ant-Design的最佳实践

    前言 阿特伍德定律,指的是any application that can be written in JavaScript, will eventually be written in JavaScript,意即"任何可以用JavaScript来写的应用,最终都将用JavaScript来写" 在使用新技术的时候,切忌要一步一步的来,如果当你尝试把两门不熟悉的新技术一起结合使用,你很大概率会被按在地上摩擦,会yarn/npm和React脚手架等技术是前提,后面我会继续写PWA深入和No

  • react+ant design实现Table的增、删、改的示例代码

    本人小白一名,第一次学习react ,该资料为本人原创,采用的是react+ant design的Tabled的一个小demo,暂时只实现了增加,删除单行,多行删除有Bug,查看详情,呕心沥血耗时一周完成,禁止抄袭,转载请先留言, 1.main.jsx import React from 'react'; import ReactDom from 'react-dom'; import ExampleTable from './ExampleTable.jsx' ReactDom.render(

  • React 实现拖拽功能的示例代码

    本文介绍了React 实现拖拽功能的示例代码,分享给大家,具体如下: 实现效果: 因为工作中会用到 JIRA 所以想实现一下相似的功能,顺便学习一下 H5 的拖拽.不支持拖拽改变顺序,感觉有点麻烦,而且没必要.感觉相关的博文好少的,大部分都是直接上代码,没有解释. 图片默认可以拖动,其他元素的拖动效果同图片.正常的 div 是不能被拖动的,鼠标点击选择后移动没有效果,需要加  draggable="true" 使得元素可以被拖动. 拖拽相关的几个事件,有被拖动元素的事件,也有拖动进入的

  • 详解React 代码共享最佳实践方式

    任何一个项目发展到一定复杂性的时候,必然会面临逻辑复用的问题.在React中实现逻辑复用通常有以下几种方式:Mixin.高阶组件(HOC).修饰器(decorator).Render Props.Hook.本文主要就以上几种方式的优缺点作分析,帮助开发者针对业务场景作出更适合的方式. Mixin 这或许是刚从Vue转向React的开发者第一个能够想到的方法.Mixin一直被广泛用于各种面向对象的语言中,其作用是为单继承语言创造一种类似多重继承的效果.虽然现在React已将其放弃中,但Mixin的

  • 详解React中共享组件逻辑的三种方式

    废话少说,这三种方式分别是:render props.高阶组件和自定义Hook.下面依次演示 假设有一个TimeOnPage组件专门用来记录用户在当前页面停留时间,像这样: const TimeOnPage = () => { const [second, setSecond] = useState(0); useEffect(() => { setTimeout(() => { setSecond(second + 1); }, 1000); }, [second]); return

  • react后台系统最佳实践示例详解

    目录 一.中后台系统的技术栈选型 1. 要做什么 2. 要求 3. 技术栈怎么选 二.hooks时代状态管理库的选型 context redux recoil zustand MobX 三.hooks的使用问题与解决方案 总结 一.中后台系统的技术栈选型 本文主要讲三块内容:中后台系统的技术栈选型.hooks时代状态管理库的选型以及hooks的使用问题与解决方案. 1. 要做什么 我们的目标是搭建一个适用于公司内部中后台系统的前端项目最佳实践. 2. 要求 由于业务需求比较多,一名开发人员需要负

  • 详解java代码中init method和destroy method的三种使用方式

    在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. 周末对这两个方法进行了一点学习和整理,倒也不是专门为了这两个方法,而是在巩固spring相关知识的时候提到了,然后感觉自己并不是很熟悉这个,便好好的了解一下. 根据特意的去了解后,发现实际上可以有三种方式来实现init method和destroy method. 要用这两个方法,自然先要知道这两

  • 详解react组件通讯方式(多种)

    1.父组件向子组件传值 父组件向子组件传值一般采用props属性传递 父组件: import React from 'react' import Child from './Child' const dataList = [ { id: '001', value: '张三' }, { id: '002', value: '李四' } ] const Parent = props => { return ( <ul> <Child dataList={dataList}><

  • 详解react hooks组件间的传值方式(使用ts)

    目录 父传子 子传父 跨级组件(父传后代) 父传子 通过props传值,使用useState来控制state的状态值 父组件 Father.tsx里: 子组件 Child.tsx里: 展示效果: 子传父 跟react的方式一样,像子组件传入回调函数,通过接收子组件的返回值,再去更新父组件的state 父组件,Father.tsx里: 子组件,Child.tsx里: 展示效果: 子传父优化版,使用useCallback存放处理事件的函数 父组件,Father.tsx里: 子组件,Child.tsx

  • 详解React中的不可变值

    什么是不可变值 函数式编程是指程序里面的函数和表达式都能像数学中的函数一样,给定了输入值,输出是确定的.比如 let a = 1; let b = a + 1; => a = 1 b = 2; 变量b出现,虽然使用了变量a的值,但是没有修改a的值. 再看我们熟悉的react中的代码,假如初始化了this.state = { count: 1 } componentDidMount() { const newState = { ...state, count: 2 }; // { count: 2

  • 详解React中的this指向

    打算记流水账一般细数一下 React 中的 this 指向问题,具体流程按事件三要素:起因,经过,结果.哈哈哈哈哈! 起因: 众所周知,React 的设计是响应式的,使用者无需操纵 DOM,操纵数据,页面就会渲染更新. 数据一变就更新,是更新所有的 DOM 吗?当然不是,哪些变了就重新渲染哪些.那就要对数据变化前后的 DOM 进行比较.直接对比真实 DOM 吗?这样性能会很低,React 比较的是虚拟 DOM,虚拟 DOM 也是对象,只不过相较真实 DOM而言,少了很多属性,更"轻".

  • 详解React Hooks是如何工作的

    1. React Hooks VS 纯函数 React Hook 说白了就是 React V18.6 新增的一些 API,API的本质就是提供某种功能的函数接口.因此,React Hooks 就是一些函数,但是 React Hooks 不是纯函数. 什么是纯函数呢?就是此函数在相同的输入值时,需产生相同的输出,并且此函数不能影响到外面的数据. 简单理解就是函数里面不能用到在外面定义的变量,因为如果用到了外面定义的变量,当外面的变量改变时会影响函数内部的计算,函数也会影响到外面的变量. 对于 Re

  • 一文详解React Redux使用方法

    目录 一.理解JavaScript纯函数 1.1 纯函数的概念 1.2 副作用概念的理解 1.3 纯函数在函数式编程的重要性 二.Redux的核心思想 2.1 为什么需要 Redux 2.2 Redux的核心概念 2.2.1 store 2.2.2 action 2.2.3 reducer 2.3 Redux的三大原则 2.3.1 单一数据源 2.3.2 State是只读的 2.3.3 使用纯函数来执行修改 2.4 Redux 工作流程 三.Redux基本使用 3.1 创建Store的过程 3.

随机推荐