随着应用程序的增长并开始涉及许多组件、更复杂的用户交互以及可能与后端服务的通信,您可能会发现使用基础状态管理方法组织代码可能会变得难以维护。
考虑这个例子:
以这种方式管理状态存在几个挑战:
- 通过对
tasks
、numberOfTasks
进行多次 createSignal
调用以及对 completedTasks
进行 createMemo
函数调用,增加了代码冗余。此外,每次状态更新时,都需要手动更新其他相关状态,这可能导致应用程序不同步。
- 虽然 Solid 已经经过优化,但该组件设计会导致频繁的重新计算,例如每次切换交互都会更新
completedTasks
,这可能会对性能产生负面影响。此外,组件逻辑对 numberOfTasks
和 completedTasks
当前状态的依赖可能会使代码理解变得复杂。
随着像这样的应用程序扩展,以这种方式管理状态变得更加复杂。引入其他依赖状态变量将需要更新整个组件,这可能会引入更多错误。这可能会使在不转移大部分状态管理逻辑的情况下将特定功能分离成不同的、可重用的组件变得更加困难。
通过使用 Stores 重新创建此列表,您将看到 Stores 如何提高代码的可读性和管理性。
如果您对 stores 的概念不熟悉,请参阅 stores 章节。
要减少原始示例中使用的 signals 数量,您可以使用 store 执行以下操作:
通过使用 store,您不再需要跟踪 tasks
、numberOfTasks
和 completedTasks
这些单独的信号。
创建 store 后,可以通过 createStore
函数返回的第一个值直接访问这些值:
通过 state.numberOfTasks
,将显示 numberOfTasks
属性中保存的 store 值。
当您想要修改 store 时,可以使用 createStore 函数返回的第二个元素。此元素允许您对 store 进行修改,从而添加新属性并更新现有属性。
但是,由于 store 中的属性是延迟创建的,因此在组件函数体中设置属性而不创建响应作用域将不会更新该值。要创建 signal 使其响应式更新,您必须访问跟踪作用域内的属性,例如使用 createEffect
:
要将元素添加到数组(在本例中为新任务),您可以通过 state.tasks.length
添加到数组的下一个索引:
store 中的 setter 遵循路径语法: setStore("key", value)
。在 addTask
函数中, tasks
数组通过 setState("tasks", state.tasks.length, { id: state.tasks.length, text, completed: false })
添加,这是一个实际的例子。
在需要进行多个 setState
调用并定位多个属性的情况下,您可以使用 Solid 的 produce
工具函数来简化代码并提高可读性。
例如切换函数:
可以使用 produce
进行简化:
了解使用 produce 的其他优点。
Info: 使用 produce 的另一个好处是它提供了一种修改 store 的方法,而无需进行多个 setStore 调用。
更新后的示例:
随着应用程序的增长并变得复杂,组件之间共享状态可能成为一个挑战。将状态和函数从父组件传递到子组件,尤其是跨多个层级,通常称为“prop drilling”。
Prop drilling 可能会导致代码冗长且难以维护,并且会使应用程序中的数据流更难以遵循。为了解决这个问题并提供更具可扩展性和可维护性的代码库,Solid 提供了 context 。
要使用它,您需要创建一个上下文。该上下文将有一个默认值,并且可以由任何后代组件使用。
您的组件将使用上下文中的 Provider
进行包装,并传递您希望共享的值。
在任何后代组件中,您可以使用 useContext
使用上下文值:
如需更深入的了解,请参阅我们有关上下文章节。