React 的学习笔记
记录一些学习 React 路上的问题或者技巧。
React 解析
setState
setState 是一个异步函数,可以传入两个参数,第一个是改变的值,第二个是修改的回调函数。setState 内部有机制,可以将几个 setState 合并执行,提升效率,因此直接如下写法:
1 | this.setState({ name: "name" }); |
然后立即取得 name 的值,很可能并无变化。使用传入状态计算函数就可以让 setState 立即执行,如下:
1 | this.setState(function(prevState, props) { |
redux -> reducer 为什么不能在 reducer 里面直接修改 state
在 redux-devtools 中,我们可以查看到 redux 下所有通过 reducer 更新 state 的记录,每一个记录都对应着内存中某一个具体的 state,让用户可以追溯到每一次历史操作产生与执行时,当时的具体状态,这也是使用 redux 管理状态的重要优势之一.
若不创建副本,redux 的所有操作都将指向内存中的同一个 state,我们将无从获取每一次操作前后,state 的具体状态与改变,若没有副本,redux-devtools 列表里所有的 state 都将被最后一次操作的结果所取代.我们将无法追溯 state 变更的历史记录.创建副本也是为了保证向下传入的 this.props 与 nextProps 能得到正确的值,以便我们能够利用前后 props 的改变情况以决定如何 render 组件
还有 reducer 必须是纯函数,好像不能使用 Math、Date 之类的函数。
纯函数:给定固定的输入就一定有固定的输出,且无副作用。
关于 Redux 框架,Reducer 中 state 处理方式的探讨
为什么要使用 actionTypes
首先是大家都这么写,这是一个默认的规范。其次最主要是使用这种方式可以有错误提示,而直接使用字符串无错误提示。
redux-thunk 的使用
yarn add redux-thunk
import {createStore,applyMiddleware,compose} from 'redux'
import thunk from 'redux-thunk'
1 | const composeEnhancers = |
如何使用:返回一个函数 外部调用此 action 的时候会执行这个 action
1 | import axios from "axios"; |
React Hooks
自定义 React Hooks
自定义一个 hook 挺简单的,其实就是一个函数
1 | import React, { useState, useEffect } from "react"; |
使用的时候
1 | import React, { useEffect, useState } from "react"; |
定义一个 hook 并传入 props
1 | import React from "react"; |
常用技巧
react 使用 lib-flexible 和 postcss-px2rem 开心的适配
react 基础环境搭建
React + TS + Less
yarn eject
yarn add less less-loader --dev
config -> webpack.config.js 里面添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32const lessRegex = /\.(less)$/;
const lessModuleRegex = /\.module\.(less)$/;
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders({
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
},
'less-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using less
// using the extension .module.scss or .module.less
{
test: lessModuleRegex,
use: getStyleLoaders({
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
camelCase: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'less-loader'
),
},以上两段代码比照着 sass 在配置里面添加
如果是 ts 项目 还需要在 src 根目录下面加一个 typings 文件夹 然后添加对应的定义问题 例如: styles.d.ts
1
2declare module "*.css";
declare module "*.less";camelCase: true,
这个属性 用来处理导出的*.module.less
横杠写法为驼峰式写法。是css-loader里面的属性配置,其余属性看文档。
常见问题
用 TS 写 React
TS 写 React 要按照约定在 extends React.Component 的时候接收两个泛型,第一个是 Prop 泛型,第二个是 State 泛型,这样在接下来的代码中才可以使用定义的数据。
1
2
3
4interface HeaderState {
searchBoxActivated: boolean;
}
class Header extends Component<any, HeaderState> {}TS 项目中遇到引入样式或者 Module 报错的情况,在根目录下创建对应的*.d.ts 文件定义模块。style.d.ts
declare module "*.module.styl";
module.d.tsdeclare module "react-transition-group";
以下代码报错
1
2const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;解决方式如下:
1
2const composeEnhancers =
(<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
第三方库
classnames
可以合并class
第三方库问题
- 若要同时使用 CSS-Module 和
react-transition-group
库,定义的 className 会不生效。
解决办法:对应的 jsx 文件同时引入style.styl
和style.module.styl
文件,并且修改的样式要写在 styl 文件而不要写在 module.styl 文件,不然插件不会生效。