【随笔】写写 React 中的一些小小知识点

Posted by ARTROY on 2019-11-12

一、this.setState()相关信息?

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
constructor(props) {
super(props);
this.state = {
num: 100,
}
}

componentDidMount() {
/* 情况一 */
this.setState({num: this.state.num+1});
console.log(this.state.num);
// 数据会发生更改,但是console.log()出来的结果是100,因为是setState()是异步操作
this.setState({num: this.state.num+1},() => {
// 第二参数是回调函数,酱紫修改就能获取到更改后的值
console.log(this.state.num);
});

/* 情况二 */
this.setState({num: this.state.num+3});
this.setState({num: this.state.num+2});
this.setState({num: this.state.num+1});
// setState 是通过队列机制实现 state 更新的,
// 当执行 setState 时,会将需要更新的state合并放入状态队列,
// 不会立刻更新,会批量更新(一个生命周期内所有的 setState 方法合并后操作)
// 最后num值是101

// 如果硬是要setState分步执行又要生效
// 那可以按函数形式去执行,最后结果是106(如果新值依赖旧值,那么也建议用函数的方式)
// 批量执行:
this.setState(prevState => {
return {
num: prevState.num + 3,
}
});
this.setState(prevState => {
return {
num: prevState.num + 2,
}
});
this.setState(prevState => ({
num: prevState.num + 1
}));

/* 情况三: 扩展题 */
this.setState({num: this.state.num + 1});
console.log(this.state.num);
this.setState({num: this.state.num + 1});
console.log(this.state.num);
setTimeout(() => {
this.setState({num: this.state.num + 1});
console.log(this.state.num);
this.setState({num: this.state.num + 1});
console.log(this.state.num);
}, 0);
// 输入:100、100、102、103
// 解析:事务(transaction)
}

二、手动进行事件绑定分别是什么,有啥区别?

(1)bind方法: <button onClick={this.handleClick.bind(this, 'test')}>Test</button>;
(2)构造器内声明: this.handleClick = this.handleClick.bind(this) and
<button onClick={this.handleClick}>Test</button>
(3)箭头函数:<button onClick={() => this.handleClick()}>Test</button>,自动绑定了定义此函数作用域的 this
思考:bind(this)可能会导致重复绑定,尽量使用箭头函数绑定(性能优化的时候也可以提一提)。

三、Hook(16.8)

目标:不编写 class 的情况下使用 state 以及其他的 React 特性。
特点:
(1)无需修改组件结构的情况下复用状态逻辑。
(2)可将组件相互关联的部分拆分成更小的函数,复杂组件将变得容易理解。
(3)更简洁、更容易理解的代码。

1、状态钩子 State Hook useState

1
2
3
4
5
6
7
8
const [name] = useState('name‘);
const [count, setCount] = useState(0);
const [arrs, setArrs] = useState(['text1’, ‘text2’]);

const fun1 = () => setCount(count + 1);
// setArrs(f) 更改了arrs的值
const fun2 = () => arrs.map(i => <li onClick={() => setArrs(f)}>{i}</li>)
const fun3 = () => setArrs([...arrs, name]);

2、副作用钩子 Effect Hook useEffect
现在做的是事情对组件的状态和 UI 有影响。 订阅了数据有更改就更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 副作用钩子会在每次渲染时执行
useEffect(() => {
...
})
// 如果副作用只打算执行一次,传递第二个参数为[]
// 表示;表示没有任何依赖 类似 componentDidMount
// 传入 count 的话表示 count 没有改变就不会更新
useEffect(() => {
...
}, [])
useEffect(() => {
...
}, [count])

3、自定义钩子 Custom Hook
自定义hook是一个函数,名称用“use”开头,函数内部可以调用其他钩子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// useEffect 不能在组件里面设置
import React, {useState, useEffect} from 'react';

export default function Test() {
function useValue(payload) {
const [val, setValues] = useState('value');
useEffect(() => {
setTimeout(() => {
setValues('payload');
})
})
return val;
}

const [count, setCount] = useState(0);
const val = useValue('122');
return (
<div>
{val ? val : ''}
</div>
);
}

4、 其他钩子
useContextuseReduceuseCallbackuseMemo
注:如果要进行数据优化,不更改就不渲染,可以使用useCallbackuseMemo

Context

组件跨层级通信 Context 相关 API
React.createContext
Context.Provider
Class.contextType
Context.Consumer

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 1、创建上下文 Provider里面的值只有Consumer接收到
import React, {useState, useEffect, useContext} from 'react';

const myContext = React.createContext();
const { Provider, Consumer } = myContext;

// 使用方式一:Consumer
function Child(props) {
return (
<div>
<p>{props.info}</p>
<p>{props.age}</p>
</div>
)
}

// 使用方式二:使用hock
function Child2(props) {
const ctx = useContext(myContext);
return (
<div>
<p>Child2</p>
<p>{ctx.age}</p>
</div>
)
}

// 使用方式三:使用class指定static contextType
class Child3 extends React.Component {
static contextType = myContext;
render() {
return (
<div>
<p>Child3</p>
<p>{this.context.age}</p>
</div>
)
}
}

export default function TestContext() {
return (
<div>
<Provider value={{info: 'name', age:123}}>
<Consumer>
{value => <Child {...value}/>}
</Consumer>
<Consumer>
{value => <Child2 {...value}/>}
</Consumer>
<Consumer>
{value => <Child3 {...value}/>}
</Consumer>
</Provider>
</div>
);
}


支付宝打赏 微信打赏

欣赏此文,打赏一下



-->