foloin
foloin

Reputation: 11

Is this normal that each list item in Solidjs is mounting on every change?

Is this normal that each list item in Solidjs is mounting on every change?

import { Component, createSignal, For } from 'solid-js';

const data = [
  {name: 'Helen'},
  {name: 'Peter'},
  {name: 'Maksim'},
]

const Card: Component = (props: {name: string}) => {
  console.log('card'); // It runs on every click which I'm not expecting 

  return <div>
   <span>Name: </span>
   <span>{props.name}</span>
 </div>
}

export const App: Component = () => {
  const [users, setUsers] = createSignal(data)

  return (
    <>
      <button onClick={() => setUsers(users => users.map(user => ({...user, name: 'Suzy'})))}>Click</button>
      <For  each={users()}>{user => <Card {...user} />}</For>
    </>
  );
};

The same happens with createStore.

Upvotes: 0

Views: 236

Answers (1)

snnsnn
snnsnn

Reputation: 13698

That is normal because you are updating every list item inside setUsers by mapping over items and creating a new object that has the same values. Although you use previous values, you are creating new object.

For keeps the reference of an item if the array item does not change. Its internal logic is something like this:

const cache = {};
cache[user] = <Card />

Since you are changing every array items, invalidating the cache by throwing away the old key, hence a new item is rendered. When this new item is rendered, Card is mounted.

Try this code, in this one we are updating only the first item:

import { Component, createSignal, For } from 'solid-js';
import { render } from 'solid-js/web';

const data = [{ name: 'Helen' }, { name: 'Peter' }, { name: 'Maksim' }];

const Card: Component<{ name: string }> = (props) => {
  console.log(props.name);
  return (
    <div>
      <span>Name: </span>
      <span>{props.name}</span>
    </div>
  );
};

export const App = () => {
  const [users, setUsers] = createSignal(data);

  const handleClick = () =>
    setUsers((users) => [
      ...users.map((val, i) => (i === 0 ? { ...val } : val)),
    ]);

  return (
    <>
      <button onClick={handleClick}>Click</button>
      <For each={users()}>{(user) => <Card {...user} />}</For>
    </>
  );
};

render(App, document.body);

Upvotes: 1

Related Questions