Does createStore
make any sense at all?
#2390
Replies: 2 comments 1 reply
-
There are ways to avoid using stores but to truly be equivalent you need to nest signals not derived memos. Memo's in this case are all intwined. I can show this with console.logs easiest. Let me take something like your example but put 2 effects at the end. Compare the difference between the console.logs for signals and stores here: https://playground.solidjs.com/anonymous/28887e8b-bb5c-4008-a2a0-8814f44e9810. As you can see the store doesn't notify every single memo that is derived from it. This is the selector problem in the React space. You update Redux and every component that listens to redux needs to determine if it needs to re-run. Whereas with granularity you can avoid that. Now this is a trivial example but consider now that your nested object contains arrays. Like a Todo list and you want to update one of the items to complete. If you just used a single signal then the whole list has to notify updates to propagate it down. const [todos, setTodos] = createSignal([]);
// picture rendering a list something like:
createMemo(() => todos().map(todo => <Todo todo={todo} />)
// and updating you do something like this,
// immutable clone and update the todo with matching id
function toggleTodo(id) {
setTodos(todos => todos.map(todo => todo.id !== id ? todo : { ...todo, completed: !todo.completed }));
} The problem is that by updating todos you trigger the whole memo to re-run. Which would recreate all the components. In React that is fine because they remake VDOM.. but it is also unnecessary.. We have our createMemo(() => memoizedMap(todos(), todo => <Todo todo={todo} />) This way it will only recreate the row with the checked has changed. But why recreate a row at all? The reason for this is that we needed to map and clone on set above so that referential equality checks were satisfied, but with fine-grained stores we don't need to notify top level. Instead we can: function toggle(id) {
const index = todos.findIndex(todo => todo.id === id)
setTodos(index, "completed", v => !v);
} Just update the one todo without triggering the whole thing. In that way the map function doesn't even run again. No components are recreated, and just the effect that shows the completed state on the todo.. maybe crossing it out updates. You can see this in action in our tutorial before and after: https://www.solidjs.com/tutorial/stores_createstore Hopefully that makes sense. This is an odd idea coming from React since they are incapable of this level of precise update. Even with the fine-grained state libraries like Jotai and even with their compiler. We've come to accept this but in SolidJS we can do better. |
Beta Was this translation helpful? Give feedback.
-
I think I have fully understood the problem you are describing. It is possible to get around without |
Beta Was this translation helpful? Give feedback.
-
Personally, I don't use
createStore
in my project even for more complex data because there is a bit too much ‘magic’ there for me and usingcreateSignal
I can handle react-js without any problems and I already explain what I think about all thisExample from react-js
and react handles the reactivity after the setter is called
Example solid-js
I use
useMemo
orcreateMemo
which basically gives the same results in both solutions and I don't understand why we need to set ProxyBeta Was this translation helpful? Give feedback.
All reactions