React中函数式组件的优化

使用React做开发的时候,当组件数目多的时候,不可避免的就需要对组件做出优化,以提高性能。对于类式组件,非常简单,只需要继承PureComponent就可以了,剩余的事情React就会帮你做好。那么,自从有了Hooks之后,在开发中更为常用的函数式组件该怎样做优化呢?

image
Source: Pixabay

为了把问题说清楚,先通过一个简单的例子演示一下为什么需要优化。

首先,实现了一个如下图所示的函数式组件,其中包含了父子两个组件:

image

其源代码很简单:

import React from 'react'
import './index.css'

export default function Parent() {

    const [name, changeName] = React.useState("Jack")

    const change = () => {
        changeName('Luke')
    }

    console.log('render parent')

    return (
        <div className="parent">
            <h4>Parent component</h4>
            <h4>My name is: {name}</h4>
            <button onClick={change}>Change name</button>
            <hr/>
            <Child/>
        </div>
    )
}

const Child = () => {

    console.log('render child')

    return (
        <div className="child">
            <h4>Child component</h4>
        </div>
    )
}

接下来,当我们单击”Change name”这个按钮的时候,会更新父组件的状态,因此会导致父组件的重新渲染。而子组件中没有任何更新,因此是不需要进行重新渲染的。

可实际情况确是:当我们单击按钮的时候,子组件也会被重新渲染:
image

当页面中组件数目较多时,可以想象这对效率的影响。那么,怎样才能对React的函数式组件进行优化呢?答案是使用memo。其实它最早的名字不叫memo,而是叫做pure,只不过这很容易和函数式编程中的概念混淆,因此最终被改成了memo。

首先是要引入memo:

import React,{memo} from 'react'

然后用memo把组件包裹起来,说白了就是一个高阶函数:

export default memo(function Parent() {

...

})

const Child = memo(() => {

...

})

再单击”Change name”按钮,可以看到,子组件不会再被重新渲染了。

image

我想之所以叫做memo,就是把函数式组件的返回值给记住了,如果下次和这次的返回值一样,就不用渲染了。

参考资料:https://blog.logrocket.com/react-pure-components-functional/

React学习笔记

把React学习过程中需要注意的一些事项记录一下。

关于代码组织

第三方库,e.g. bootstrap.css 放于 public目录下
组件采用: src/components/SearchDetails/index.jsx/index.css

state

操作state的方法要和state放在同一个组件中。

组件之间传递参数的方法

从父组件传递给子组件,直接使用props
从子组件传递给父组件,从父组件通过props传递给子组件一个回调函数,在子组件中调用该函数并传回参数
任何组件间传递消息:https://github.com/mroderick/PubSubJS

路由

在使用NavLink的时候,默认活跃导航条使用的css类名为’active’,而这正好和bootstrap中活跃导航条目类名相同,因此如果使用bootstrap的话,无需注明。

<NavLink className="xxx" to="/x1">X1</NavLink>
<NavLink className="xxx" to="/x2">X2</NavLink>

但如使用其他框架,则需要使用activeClassName注明。

<NavLink activeClassName="my_active_class" className="xxx" to="/x1">X1</NavLink>
<NavLink activeClassName="my_active_class" className="xxx" to="/x2">X2</NavLink>

同时,在public/index.html中(或相应css文件中)定义类my_active_class

CORS

如果只有一个CORS需要访问时

在一个组件中跨域发出请求时,需要配置代理。否则能否发送请求,但无法接收返回信息。

更改package.json,添加:

"proxy": "http://www.cors-site.com"

如果有多个外域需要访问时

创建setupProxy.js,并添加:

// CJS syntax
const proxy = require('http-proxy-middleware')

module.exports = function(app){
  app.use(
    proxy('/api1',{
      target:'http://www.cors-site1.com',
      changeOrigin:true,
      pathRewrite:{'^/api1':''}
    }),
    proxy('/api2',{
      target:'http://www.cors-site2.com',
      changeOrigin:true,
      pathRewrite:{'^/api2':''}
    }),
  )
}

环境变量的使用

如果要想在.env中定义环境变量,需要给变量加前缀:REACT_APP_

例如:

REACT_APP_API_SERVER=http://localhost:4000

使用:

const response = await fetch(`${process.env.REACT_APP_API_SERVER}/books`);

VS相关插件

ES7 React/Redux/GraphQL/React-Native
Simple extensions for React,Redux and Graphql in JS/TS with…
by dsznajder

每天进步一点点-在React中使用Chart.js

最近尝试开始使用React,发现真的非常好用。这次尝试了在一个单一的页面中使用React+Chart.js来生成基本的报表。这里并没有创建一个完整的React项目。其原因在于,在现有的一个基于Java(后端)+JQuery(前端)的项目中只需要添加一个页面,只在该页面中使用React。下面把步骤记录一下:

阅读更多