ReactJS - 道具与状态 + 商店设计
ReactJS - props vs state + Store designing
想象一下:
您正在编写一个 'smart-house' 应用程序来管理您家中的温度。
在我看来我想:
- 查看每个房间的当前温度
- 为每个房间设置所需的温度
- 查看每个房间是否开空调on/off
有一个外部设备,通过 websockets 与您的应用程序通信(它会定期发送当前温度、空调状态)。
我看到两个选项:
1) 创建一个 'big' 存储包含如下数据结构:
var _data = [
name: 'Kitchen',
currentTemperature: 25,
desiredTemperature: 22,
sensors: [
{
name: 'Air Conditioning'
state: 'on'
}
... there might be other sensors too ...
]
]
会有一个 TemperatureManager 组件(或类似的东西)。它会有一个状态并定期从 Store 中获取它。
然后它会将状态的一部分分发给他的后代(即RoomTemperatureManager,RoomSystemSensorManager),将其作为道具传递。
如果有任何变化(例如,卧室的温度),它将从存储中获取所有数据并在必要时重新渲染其后代。
2)第二种方案是
让 RoomTemperatureManagers 和 RoomSystemSensorManagers 有自己的状态。它还与温度和 SystemSensorState 的独立存储有关。
这些 Store 将使用参数化的 getter(即 getSensorState(roomName))而不是方法来获取所有数据。
问题:
哪个选项更好?
补充问题:
叶子组件(即负责管理所需温度的组件)直接调用ActionCreator 可以吗?或者也许只有监督组件应该知道关于 ActionCreator 的任何事情并且应该将适当的方法作为 属性 传递给他的后代?
我认为最好的方法是授权。您的 TemperatureManager 应该有一种机制来通知侦听器有更新,而 Room(Temperature|System)Manager 将作为listener 一个回调,它将使用更新的数据并相应地更改状态。这将利用虚拟 DOM diff,因此仅显示更改,而不是重新渲染整个部分,并创建一个可以与商店通信的单点。 Room(Temperature|System)Manager 应仅在需要对正在使用的模型进行更新时才与 Store 通信。
TemperatureManager 如果在订阅时可以改进,您可以指定要收听哪些数据以进行更新。它不应该假定特定的 'manager' 应该获得数据的任何子集。
您在 post 中描述的 2 个选项实际上是 2 个不同的问题:
- 一家大店还是几家不同的店?
- 子组件 (RoomTemperatureManagers) 应该有自己的状态还是从商店接收道具?
Ad 1. 只要不复杂,一个大商店就容易多了。我使用的经验法则:如果您的商店有 > 300 行代码,最好分开在不同的商店。
广告 2. 道具通常比状态好。但在你的情况下,我认为你需要状态,例如你的温度管理器:你在你的应用程序中设置温度(并希望看到它反映在一些滑块或其他东西中)。为此,您将需要状态。
- 状态立即更新前端(乐观更新)。
- 然后该组件将 set_temparature 动作发送到
屋。
- 然后房子里的传感器确认它已经设置了新的
温度到您的应用程序。
- 商店更新并发出零钱。
- 房屋中传感器的温度设置传达为
道具给你的温度管理器。
- Temperature 管理器会做任何它需要做的事情(简单地用新的属性更新状态,显示确认消息,或者如果通信链出现故障,则显示漂亮的错误消息)。
想象一下: 您正在编写一个 'smart-house' 应用程序来管理您家中的温度。
在我看来我想:
- 查看每个房间的当前温度
- 为每个房间设置所需的温度
- 查看每个房间是否开空调on/off
有一个外部设备,通过 websockets 与您的应用程序通信(它会定期发送当前温度、空调状态)。
我看到两个选项:
1) 创建一个 'big' 存储包含如下数据结构:
var _data = [
name: 'Kitchen',
currentTemperature: 25,
desiredTemperature: 22,
sensors: [
{
name: 'Air Conditioning'
state: 'on'
}
... there might be other sensors too ...
]
]
会有一个 TemperatureManager 组件(或类似的东西)。它会有一个状态并定期从 Store 中获取它。 然后它会将状态的一部分分发给他的后代(即RoomTemperatureManager,RoomSystemSensorManager),将其作为道具传递。
如果有任何变化(例如,卧室的温度),它将从存储中获取所有数据并在必要时重新渲染其后代。
2)第二种方案是
让 RoomTemperatureManagers 和 RoomSystemSensorManagers 有自己的状态。它还与温度和 SystemSensorState 的独立存储有关。
这些 Store 将使用参数化的 getter(即 getSensorState(roomName))而不是方法来获取所有数据。
问题:
哪个选项更好?
补充问题:
叶子组件(即负责管理所需温度的组件)直接调用ActionCreator 可以吗?或者也许只有监督组件应该知道关于 ActionCreator 的任何事情并且应该将适当的方法作为 属性 传递给他的后代?
我认为最好的方法是授权。您的 TemperatureManager 应该有一种机制来通知侦听器有更新,而 Room(Temperature|System)Manager 将作为listener 一个回调,它将使用更新的数据并相应地更改状态。这将利用虚拟 DOM diff,因此仅显示更改,而不是重新渲染整个部分,并创建一个可以与商店通信的单点。 Room(Temperature|System)Manager 应仅在需要对正在使用的模型进行更新时才与 Store 通信。
TemperatureManager 如果在订阅时可以改进,您可以指定要收听哪些数据以进行更新。它不应该假定特定的 'manager' 应该获得数据的任何子集。
您在 post 中描述的 2 个选项实际上是 2 个不同的问题:
- 一家大店还是几家不同的店?
- 子组件 (RoomTemperatureManagers) 应该有自己的状态还是从商店接收道具?
Ad 1. 只要不复杂,一个大商店就容易多了。我使用的经验法则:如果您的商店有 > 300 行代码,最好分开在不同的商店。
广告 2. 道具通常比状态好。但在你的情况下,我认为你需要状态,例如你的温度管理器:你在你的应用程序中设置温度(并希望看到它反映在一些滑块或其他东西中)。为此,您将需要状态。
- 状态立即更新前端(乐观更新)。
- 然后该组件将 set_temparature 动作发送到 屋。
- 然后房子里的传感器确认它已经设置了新的 温度到您的应用程序。
- 商店更新并发出零钱。
- 房屋中传感器的温度设置传达为 道具给你的温度管理器。
- Temperature 管理器会做任何它需要做的事情(简单地用新的属性更新状态,显示确认消息,或者如果通信链出现故障,则显示漂亮的错误消息)。