渲染当前活跃用户
首先,我们需要创建一个动作,当点击联系人时触发该动作。此动作将设置当前活跃用户,这是构建聊天窗口的第一步。
以下是完整的聊天窗口布局:

请看一下 <Main /> 组件中的逻辑。只有当 activeUserId 存在时,<ChatWindow /> 才会被显示。
目前,activeUserId 被设置为 null。
我们需要确保每当点击某个联系人时,都能正确设置 activeUserId。
你觉得该怎么做?
我们需要派发一个 action,对吧?
没错!
接下来我们来定义这个 action 的结构。
记住,一个 action 只是一个包含 type 字段和 payload 的普通对象。
其中 type 字段是必需的,而 payload 的字段名可以自定义,不过使用 "payload" 是一种常见且推荐的做法。
因此,这个 action 的结构如下所示:
1{ 2 type: "SET_ACTIVE_USER_ID", 3 payload: user_id 4}
该 action 的类型(即名称)将命名为 SET_ACTIVE_USER_ID。
顺便提一下,在 action 类型中通常使用大写下划线命名法(snake case),例如写成 SET_ACTION_ID,而不是 "setactionid" 或 "set-action-id"。
此外,action 的 payload 将是被设为当前活跃用户的用户 ID(user_id)。
现在我们开始在用户交互时派发 action。
由于这是本项目中首次派发 action,我们先创建一个新的 actions 目录,同时创建一个 constants 目录。
在 constants 目录下新建一个文件:action-types.js。
该文件的唯一职责就是集中管理所有的 action 类型常量。稍后我会解释这样做的重要性。
在 action-types.js 中写入以下内容:
constants/action-types.js:
1export const SET_ACTIVE_USER_ID = "SET_ACTIVE_USER_ID";
那么,为什么要这样做呢?
要理解这一点,我们需要看看在 Redux 应用中 action 类型会在哪些地方被使用。
在大多数 Redux 应用中,它们通常出现在两个位置:
(1) Reducer 中:
你在 reducer 中通过 switch 判断 action.type:
1switch(action.type) { 2 case "WITHDRAW_MONEY": 3 doSomething(); 4 break; 5}
(2) Action Creator 中:
在 action creator 中,你也可能会写出类似这样的代码:
1export const setWithdrawAmount = amount => ({ 2 type: "WITHDRAW_MONEY", 3 payload: amount 4})
现在再看上面 reducer 和 action creator 的代码,它们有什么共同点?
都是字符串 “WITHDRAW_MONEY”!
随着应用规模扩大,这类字符串越来越多,你(或他人)可能某天会不小心写成 ”WITDDRAW_MONEY” 或 ”WITHDRAW_MONY”,而不是正确的 ”WITHDRAW_MONEY”。
我想强调的是:直接使用字符串字面量很容易导致拼写错误。
根据经验,由拼写错误引发的 bug 非常令人头疼——你可能花很长时间排查,最后发现只是少了一个字母。
为了避免这种麻烦,
一个好办法是将这些字符串定义为常量并存放在单独的文件中。这样,你无需在多处重复书写原始字符串,只需导入已定义的常量即可。
你只需要声明一次常量,却可以在多个地方复用,从而彻底避免拼写错误。
这正是我们创建 constants/action-types.js 文件的原因。
接下来,我们创建对应的 action creator。
actions/index.js:
1import { SET_ACTIVE_USER_ID} from "../constants/action-types"; 2export const setActiveUserId = id => ({ 3 type: SET_ACTIVE_USER_ID, 4 payload: id 5});
如你所见,我从 constants 目录导入了 action type 常量,正如前面所解释的那样。
再次强调,action creator 只是一个函数。我将其命名为 setActiveUserId,它接收一个用户 ID 作为参数,并返回一个 action 对象,其中 type 和 payload 都已正确设置。
至此,剩下的工作就是在用户点击联系人时派发该 action,并在 reducer 中处理这个被派发的 action。
这部分内容将在下一课中讲解。