私はReactとReduxを使ってWebアプリケーションを構築していますが、私は状態の不変性に関する問題に直面しています。再帰関数(Redux)での状態変化の回避
私の状態は次のようになります -
{
tasks: [
{
id: 't1',
text: 'Task 1',
times: {
min: 0,
max: 0
},
children: [
{ id: 't1c1', text: 'Task 1 child 1', times: { min: 2, max: 3 }, children: [] },
{ id: 't1c2', text: 'Task 1 child 2', times: { min: 3, max: 4 }, children: [] }
...
]
}
...
]
}
これは「子供」配列でゼロ以上の子タスクを持つ各タスクに「タスク」オブジェクトの階層を定義します。各タスクには、このタスクが実行する最小時間( "最小")と最大時間( "最大")(時間単位)を記録する「時間」オブジェクトもあります。
私は、タスク階層を横断し、1人以上の子供を持つすべてのタスクの合計「時間」値(最小値と最大値)を計算して設定するために使用される単純な再帰関数を作成しました。したがって、上記の例では、タスク "t1"は、計算後に最小時間5(2 + 3)と最大時間7(3 + 4)を持つ必要があります。この関数は、各タスクが任意の数の祖先を持つことができるので、本質的に再帰的である必要があります。
(以下はテストを行わずにメモリから書かれていたので、無視してください/任意のタイプミスを許す)
function taskTimes(tasks)
{
let result = { min: 0, max: 0 };
if (tasks.length === 0)
return result;
tasks.forEach(task => {
if (task.children.length > 0)
{
let times = taskTimes(task.children);
task.times.min = times.min; // MUTATING!
task.times.max = times.max; // MUTATING!
result.min += times.min;
result.max += times.max;
}
else
{
result.min += task.times.min;
result.max += task.times.max;
}
});
return result;
}
私が正しく作品を作成したが、私はそれを書いた前に、私は問題を抱えていることを知っていた機能:横断しながら、タスク階層、個々のタスクオブジェクト(具体的には「時間」オブジェクト)が変更されます。これは減速機で実行したいので問題です。したがって、私はこのアクションから新しい状態を作成したいのですが、それを変更するよりもむしろです。
私の質問は、状態の変異を避けるためにこのシステムを変更する最良の方法は何ですか?
Immutable.jsを使用して階層全体に不変性を適用しようとすると、これはおそらく私の次のステップです。もう1つの選択肢は、このデータをまったく保存するのではなく、必要に応じて各コンポーネントで計算することです。後者はおそらくよりクリーンな選択肢ですが、私はまだ他のプロジェクトでこれと似たようなことをする必要があると予測できるので、これにどのように取り組むべきかを知りたいのです。
この分野のベストプラクティスについてのアドバイスは大変ありがたいです。また、私が非常に明白な何かを見落としてしまったら、親切にしてください! ありがとうございます。
私は最も一般的なベストプラクティスは、リレーショナルテーブルのようなデータ構造を平坦化することだと思います。これにより、内側のキーと配列を変更することなく、新しい状態を簡単に返すことができます。 Normalizrはこれを手助けする非常に普及したツールです。https://github.com/paularmstrong/normalizr – azium
はい、これは間違いなく、特にデータがリンクされて正規化が必要な場合に適しています。おそらく、それぞれのエンティティ(タスク)を独自のキーを持つオブジェクトに入れておくと、コピーを簡単に作成できるようになるでしょう。私はそれをチェックする必要があります。私はnormalizrを見たことがなかったので、あまりにもリンクのおかげで。 – Polaris64