添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

代码地址请在 github查看 ,我将下面的例子分成了几个包来运行,你只要简单的npm run dev就可以了,也欢迎您star,issue,共同进步!

1.react中父组件的shouldComponentUpdate返回false

在React的Context API中,如果context中属性发生变化,而父组件的shouldComponentUpdate返回false,那么该父组件中所有子组件都不会监测到conext的变化,从而不会reRender。比如下面的例子中,我们的ThemeProvider中的context发生了变化,但是TodoList的属性props没有发生改变,所以TodoList的shouldComponentUpdate返回了false,那么TodoList下面产生的所有的ThemedText的颜色都不会发生变化了(没有检测到ThemeProvider的contex变化)。 代码运行请查看这里

class ThemeProvider extends React.Component {
 //Will invoke when state or props change!
  getChildContext() {
    return {color: this.props.color}
  render() {
    return <div>{this.props.children}</div>
//Add color props to context
ThemeProvider.childContextTypes = {
  color: React.PropTypes.string

上面这个ThemeProvider 组件用于将props中获取到的color属性放置到react的context中。

class ThemedText extends React.Component {
  render() {
    return <div style={{color: this.context.color}}>
      {this.props.children}
    </div>
//Will get color prop from parent Component context
ThemedText.contextTypes = {
  color: React.PropTypes.string

ThemedText 组件负责从父级组件的context中获取color来作为自己的style。

class TodoList extends React.PureComponent {
  render() {
    return (<ul>
      {this.props.todos.map(todo => 
        <li key={todo}><ThemedText>{todo}</ThemedText></li>
    </ul>)

TodoList 组件用于从props中获取到todos属性,同时根据这些属性来渲染出我们的ThemedText组件。下面给出我们最顶层的组件:

const TODOS = ["Get coffee", "Eat cookies"]
class App extends React.Component {
  constructor(p, c) {
    super(p, c)
    this.state = { color: "blue" } 
  render() {
    return (
         {/*ThemeProvider将color放到context中*/}
         <ThemeProvider color={this.state.color}>
              <button onClick={this.makeRed.bind(this)}>
                 {/*ThemedText通过this.context.color获取到父组件的color属性设置style*/}
                <ThemedText>Red please!</ThemedText>
              </button>
              <TodoList todos={TODOS} />
(1)当点击按钮的时候,按钮本身颜色发生变化,但是TodoList这个组件没有变化,因为它继承了React.PureComponent,所以组件的props没有发生变化,那么组件不会重新渲染。因此,我们的TodoList里面的所有的组件颜色都不会发生变化,因为TodoList组件的shouldComponentUpdate返回了false!!!!因此不管是TodoList还是他的子组件都不会更新
(2)更加糟糕的是,我们也不能在TodoList中手动实shouldComponentUpdate,因为SCU根本就不会接收到context数据(只有当它的state或者props修改了才能接收到,getChildContext才会调用)。
(3)因此,shouldComponentUpdate如果返回false,那么所有的子组件都不会接收到context的更新。如这里的TodoList组件返回了false,那么TodoList下所有的ThemedText从context中获取到的color都不会更新,这很重要!!!!
        </ThemeProvider>
  //rewrite color attr in state
  makeRed() {
    this.setState({ color: "red" })
ReactDOM.render(
  <App />,
  document.getElementById("container")
2.使用依赖注入(context-based Dependency Injection)

使用依赖注入(context-based Dependency Injection)来解决当ThemeProvider的context发生变化,同时TodoList的shouldComponentUpdate返回false(其Props发生了变化),而子组件不会更新的情况。其原理其实就是:不再将context作为一个容器,而是作为一个事件系统。详细代码请查看这里。此时ThemeProvider变成了如下内容:

class ThemeProvider extends React.Component {
  constructor(s, c) {
    super(s, c)
    this.theme = new Theme(this.props.color)
   * 这个方法组件在shouldComponentUpdate之前肯定是被调用的,所以我们的这个内置的Theme对象肯定可以接收到下一个状态的color
  componentWillReceiveProps(next) {
    this.theme.setColor(next.color)
  //传入到子组件中的是theme而不是我们的color属性
  getChildContext() {
    return {theme: this.theme}
  render() {
    return <div>{this.props.children}</div>
//放到子组件中的是theme
ThemeProvider.childContextTypes = {
  theme: React.PropTypes.object

我们看看我们的Theme事件系统:

class Theme {
  // this.theme = new Theme(this.props.color)
  constructor(color) {
    this.color = color
    this.subscriptions = []
  *每次setColor的时候将我们的subscription中的所有的函数都调用一遍
  setColor(color) {
    this.color = color
    this.subscriptions.forEach(f => f())
   * 调用subscribe方法来push一个函数用于执行
  subscribe(f) {
    this.subscriptions.push(f)

此时我们传递到下级组件的往往是一个Theme对象而不是一个color属性,即传递的不再是state的容器,而是一个小型的事件系统。我们再看看TodoList下的ThemedText如何在TodoList的shouldComponentUpdate返回false的情况下(props没有发生改变)进行了组件更新。

class ThemedText extends React.Component {
     * 在所有子组件中,我们在componentDidMount中我们会获取到theme然后注册我们的事件,并且强制组件更新
  componentDidMount() {
    this.context.theme.subscribe(() => this.forceUpdate())
  render() {
    return <div style={{color: this.context.theme.color}}>
      {this.props.children}
    </div>
ThemedText.contextTypes = {
  theme: React.PropTypes.object

其实我们的顶级组件压根就不需要进行改造,和上一种情况完全一致:

class App extends React.Component {
  constructor(p, c) {
    super(p, c)
    this.state = { color: "blue" } 
  render() {
    return (
           <ThemeProvider color={this.state.color}>
(1)ThemeProvider将color这个props放到context中,不过不是直接放进去,而是采用一种更加优雅的方式来完成
(2)在ThemeProvider中传递给子组件的不再是color,而是一个依赖注入系统然后所有需要接收到Context更新的组件全部subscribe这个事件即可
 (3)TodoList我们依然使用的是React.PureComponent,但是其下面的ThemedText组件却可以接收到我们的ThemeProvider的context更新(前提TodoList本身prop/state没有改变)
(4)这个事件系统的实现有点简单,我们需要在componentWillUnMount中取消
  事件监听,同时应该使用setState而不是forceUpdate让组件更新
              <button onClick={this.makeRed.bind(this)}>
                <ThemedText>Red please!</ThemedText>
              </button>
              <TodoList todos={TODOS} />
            </ThemeProvider>
  makeRed() {
    this.setState({ color: "red" })

参考资料:
How to safely use React context
Why Not To Use Context

代码地址请在github查看,也欢迎您star,issue,共同进步!1.react中父组件的shouldComponentUpdate返回false在React的Context API中,如果context中属性发生变化,而父组件的shouldComponentUpdate返回false,那么该父组件中所有子组件都不会监测到conext的变化,从而不会reRender。比如下面的例子中,我们的Th
最近在开发一个服务端渲染工具,通过一篇小文大致介绍下服务端渲染,和服务端渲染的方式方法。在此文后面有两中服务端渲染方式的构思,根据你对服务端渲染的利弊权衡,你会选择哪一种服务端渲染方式呢? 什么是服务器端渲染 使用 React 构建客户端应用程序,默认情况下,可以在浏览器中输出 React 组件,进行生成 DOM 和操作 DOM。React 也可以在服务端通过 Node.js 转换成 HTML,直接在浏览器端“呈现”处理好的 HTML 字符串,这个过程可以被认为 “同构”,因为应用程序的大部分代码都可以在服务器和客户端上运行。 为什么使用服务器端渲染 与传统 SPA(Single Page A
useForceUpdate useForceUpdate 是一个 React Hook,它强制您的函数组件重新渲染。 useForceUpdate 本身没有任何用途。 它是一个小包,旨在集成到更大的钩子中,使仍然依赖 this.forceUpdate() 的任何类功能过时。 安装 npm install use-force-update 或 yarn add use-force-update 使用 import React from 'react'; 从“use-force-update”导入 useForceUpdate; 导出默认函数 MyButton() { const forceUpdate = useForceUpdate(); const handleClick = React.useCallback(() => { alert('我现在要重新渲染。'); forceUpdate(); }, [forceUpdate]); 返回(重新渲染);
React Router如何在url参数不同的情况下跳转页面不更新解决方案说明解决方案及思路componentWillReceiveProps(nextProps) 场景如下: {item.productName} 当前页面相同的url参数不同,并不会去重新触发我们的componentDidMount函数。所以导致页面不会更新解决方案及思路 此时,我们就需要用到react生命周期中的componentWillReceiveProps函数。 componentWillReceiveProps(nextProps) 组件初次渲染时不会执行componentWillReceivePro
Context API 维护全局状态,实现全局组件通信 Context API 有 3 个关键的要素:React.createContext、Provider、Consumer。 我们通过调用React.createContext,可以创建出一组 Provider。Provider 作为数据的提供方,可以将数据下发给自身组件树中任意层级的 Consumer。 React.createContext: ​ 作用是创建一个 context 对象。 const AppContext = React.createC
React Context 案例学习:子组件更新组件的状态 一直知道 React ContextReact 内部实现状态管理的方法,也简单的跟着官方的案例敲了一下使用 Context 进行的渲染,不过始终因为 子组件更新组件组件 这一方法的实现太过麻烦,最终还是决定使用 Redux——毕竟 Redux 虽然内部实现依靠的是 Context,但是它已经封装好了。不过最近还是想要深入的学习一下 React,也就包括其状态管理机制,正好学到一个非常干净的写法,也就借此写一篇笔记。 基础的 Cont
Source Insight 最妙的地方就是点击一个符号,会在Context窗口中自动显示定义.然而事情总有例外,总有一部分人的电脑上总是不能正常工作.我就是这其中之一,点击了符号后,等到黄花菜都凉了,始终没能更新,这之间我尝试了各种办法,重装软件,换配置,换系统....都统统没有用.我怀疑它使用的鼠标勾子被什么神乎其神的东西给挡住了,然后就没有然后了..... 后来,发现了...
pages/index.js import React, { useState, createContext } from 'react' import Header from '../components/Header' export const MylistContext = createContext({}); export default function Home(list) { const color = { color: 'blue' } return (
注意: 从 React v15.5 开始 ,React.PropTypes 助手函数已被弃用,我们建议使用 prop-types 库 来定义contextTypes。 2.1首先你需要通过在终端npm install prop-types安装一个叫prop-types的第三方包 getChildContext 定义在父组件中,指定子组件可以使用的信息 childContextTypes
需求:父组件发送请求后,根据返回数据实时更新部分state,子组件实时检测跟随跟新 1、可以使用利用react的componentWillReceiveProps方法 子组件中增加 componentWillReceiveProps(nextProps:any){ this.setState({ reuploadFlag: nextProps.reuploadFlag, successFlag: nextProps.successFlag,
React context组件可以通过调用父组件提供的回调函数来修改父组件的值。具体的步骤如下: 1. 在父组件中定义一个回调函数,该函数用于修改父组件的值。 2. 将该回调函数作为属性传递给子组件。 3. 在子组件中使用 `useContext` 钩子获取父组件提供的 context 对象。 4. 在需要修改父组件值的地方,调用父组件提供的回调函数,传入需要修改的值。 下面是一个示例代码: ```jsx // 创建一个 context 对象 const MyContext = React.createContext(); // 父组件 function ParentComponent() { const [value, setValue] = useState(0); // 定义一个回调函数,用于修改父组件的值 function handleSetValue(newValue) { setValue(newValue); // 将回调函数作为属性传递给子组件 return ( <MyContext.Provider value={{ value, handleSetValue }}> <ChildComponent /> </MyContext.Provider> // 子组件 function ChildComponent() { // 使用 useContext 钩子获取父组件提供的 context 对象 const { value, handleSetValue } = useContext(MyContext); return ( <p>父组件的值:{value}</p> <button onClick={() => handleSetValue(value + 1)}>增加</button> 在上面的代码中,当用户点击子组件中的增加按钮时,会调用父组件提供的 `handleSetValue` 回调函数来修改父组件的值。这样就实现了子组件修改父组件值的功能。
优买工作室: 貌似在Ref与函数式声明组件这块 其实可以通过ref传递给函数式声明组件比如: const TextInput = React.forwardRef((props, ref) => ( <Input placeholder="Basic ref" ref={ref} maxLength={100} /> export default TextInput; 研究生实证论文数据经验分享 callmescl: 求提取码昂~ React路上遇到的那些问题以及解决方案 m0_37349455: [vite] error applying css transforms: TypeError: node.getIterator is not a function, 前辈,请问这是什么原因