在react-redux中使用connect()与componentDidMount()

背景描述

在TodoList項目中,我原本使用react-redux的connect()将store的state和dispatch通过两个参数包装在无状态组件TodoListUI上,使其成为聪明的容器组件
但我想使用componentDidMount()发送一个AJAX请求来获取list列表的初始数据,但此时 无状态组件 没有生命周期函数,所以我将 无状态组件 包裹在一个 容器组件TodoList 中,再对TodoList使用connect()连接上store

代码

TodoList.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
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import React, { Component } from 'react';
import { connect } from "react-redux";
import { getChangeInputValue, getAddItem, getDeleteItem, getTodoList } from "./store/actionCreator";


// UI组件=>无状态组件
const TodoListUI = (props) => {
const { inputValue, list, changeInputValue, handleClick, handleClickDelete } = props;
console.log(inputValue, list);//undefined undefined
return (
<div>
<div>
<input value={inputValue} onChange={changeInputValue} />
<button onClick={handleClick}>提交</button>
</div>
<ul>
{
list.map((item, index) => {
return <li key={index} onClick={() => (handleClickDelete(index))}>{item}</li>
})
}
</ul>
</div>
)
}

class TodoList extends Component {
render() {
return (
<TodoListUI/>
)
}
// 生命周期函数
componentDidMount() {
this.props.initList();
}
}

// state指store中的数据,通过mapStateToProps()将state中的数据映射到props中
const mapStateToProps = (state) => {
return {
// state中的inputValue映射到props的inputValue中
inputValue: state.inputValue,
list: state.list
}
}

// 将store的dispatch()传到组件的props中
const mapDispatchToProps = (dispatch) => {
return {
changeInputValue(e) {
const action = getChangeInputValue(e);
dispatch(action);
},
handleClick() {
const action = getAddItem();
dispatch(action);
},
handleClickDelete(index) {
const action = getDeleteItem(index);
dispatch(action);
},
initList() {
// 将异步AJAX请求放到action中
const action = getTodoList();
// 因为thunk中间件,action可以是一个函数
dispatch(action);
}
}
}

// connect让TodoList连接store,如何连接看mapStateToProps(),修改state看mapDispatchToProps()
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);

报错

报错:

1
Cannot read property 'map' of undefine

分析

调用map的对象list 打印出来是 undefined,初始化第一次渲染的时候异步数据返回之前list是undefined。
也就是说我们此时根本没有从store中获取到list数据

解决

我们在无状态组件(子组件)中其实并没有拿到store中的数据,我们可以发现现在直接使用connect包裹的组件是父组件,所以父组件拿到了store中的数据,子组件并没有,所以我们需要在调用子组件的同时将相关数据/方法传过去,这样子组件才能调用我们使用connect的两个参数绑定的store相关的数据/方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class TodoList extends Component {
render() {
const { inputValue, list, changeInputValue, handleClick, handleClickDelete } = this.props;
return (
<TodoListUI
inputValue={inputValue}
list={list}
changeInputValue={changeInputValue}
handleClick={handleClick}
handleClickDelete={handleClickDelete}
/>
)
}
// 生命周期函数
componentDidMount() {
this.props.initList();
}
}
,