我认为这更多是一个概念/体系结构问题,但我将包含代码示例以帮助解释该问题。我有一个标准化的redux状态,其中实体状态切片看起来像这样:
entities: {
projects: {
[id]: {...},
[id]: {...},
...
},
assignments: {
[id]: {...},
[id]: {...},
...
}
}
个人任务如下:
{
id: 1,
name: 'assignment 1',
status: 'active',
deadline: '01-01-2020'
}
我从后端数据库获取此数据。我正在尝试找出适当的方法来处理更新此数据,保持UI响应以及使Redux状态与后端保持同步的过程。
一个特定的示例是一个反应组件,用于显示单个任务,该任务具有一个选择器/单选按钮,可在以下之间更改状态:
const statusOptions = {
'active',
'pending',
'complete'
}
我可以看到的选项是:
1)将选择器的值设置为props.assignment.status
的值,并在选择器/选择器的onChange中调度一个updateAssignment()
操作,其中一个传奇/ thunk发送POST请求并立即触发fetchAssignment()
操作将发送GET请求并更新Redux状态,然后组件将重新呈现。
此问题是redux更新花费的时间太长,因此UI看起来很滞后,受控输入将恢复为旧选择,直到新的props传入为止。
2)基于redux状态设置本地组件状态,如下所示:
state = { status: this.props.assignment.status }
然后根据本地状态设置选择器的值,这将在值更改时提供近乎即时的UI更新。
我在这里看到的问题是,我很确定这是一个反模式,我必须使用getDerivedStateFromProps()
或类似的方法来确保本地状态与redux状态保持同步。另外,我真的很喜欢“单一事实来源”的想法,并且我觉得此选项会使它无效。
3)根据props.assignment.status
设置选择器的值,并在选择器的onChange处理程序中克隆assignment
对象,更新status
属性,然后立即发送{将本地创建的updateAssignment()
对象合并到状态中的{1}}操作。
此后,将POST请求发送到服务器,如果失败,则将Redux状态恢复为先前的状态,基本上删除了本地添加的assignment
对象。虽然这似乎有点hacky?
在维护单一真相源,快速UI和干净代码的同时,是否有商定的最佳实践来更新redux数据?
答案 0 :(得分:1)
在我看来(2)的第一部分是正确的方式。
在ComponentDidMount中(或者甚至更好的是在App.js中,当应用启动时),您将从数据库中获取数据到redux状态,并从中设置本地状态。
然后,您在本地维护数据,并调度将更新Redux状态和数据库的适当操作。
在shouldComponentUpdate中,您需要防止在此redux更新之后发生的更新:您将检查道具的值是否已更改。
在componentDidUpdate中,如果道具发生更改,您将更新状态。
最后要做的事情是在其他智能手机上运行的应用程序的其他实例或其他数据源(如果可能发生)发生数据库更改后获取数据更新。例如,在firebase中,您可以通过监听相关的应用更改来实现。我不知道这与这里是否相关。