1

I don't understand differences between For and Index, I read the following question.

SolidJS: For vs Index

I changed the code a little bit and execute in the playground.

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

function ForCats() {
  const [cats, setCats] = createSignal([
    'Keyboard Cat',
    'Maru',
    'Henri The Existential Cat'
  ]);
  
     setTimeout(() => setCats(['Keyboard Cat', 'Keyboard Cat', 'Keyboard Cat', 'New Cat']), 2000)

  return (
    <ul>
    <For each={cats()}>{(name, i) => {

        console.log(`For: rendered ${i()}:${name} whole cat`);

      return <li>
        <a target="_blank" href="">
          1: {name}
        </a>
      </li>
    }}</For>
    </ul>
  );
}


function IndexCats() {
  const [cats, setCats] = createSignal([
    'Keyboard Cat',
    'Maru',
    'Henri The Existential Cat'
  ]);
  
     setTimeout(() => setCats(['Keyboard Cat', 'Keyboard Cat', 'Keyboard Cat', 'New Cat']), 2000)

  return (
    <ul>
    <Index each={cats()}>{(name, i) => {

        console.log(`Index: rendered ${i}:${name()} whole cat`);

      return <li>
        <a target="_blank" href="">
          1: {name()}
        </a>
      </li>
    }}</Index>
    </ul>
  );
}

render(() => <><ForCats /> <IndexCats/ ></>, document.getElementById('app'))
For: rendered 0:Keyboard Cat whole cat
For: rendered 1:Maru whole cat
For: rendered 2:Henri The Existential Cat whole cat
Index: rendered 0:Keyboard Cat whole cat
Index: rendered 1:Maru whole cat
Index: rendered 2:Henri The Existential Cat whole cat
For: rendered 1:Keyboard Cat whole cat
For: rendered 2:Keyboard Cat whole cat
For: rendered 3:New Cat whole cat
Index: rendered 3:New Cat whole cat

I understand why log displays like the above, but the component which uses Index also re-renders well. I thought the result should be

1: Keyboard Cat
1: Keyboard Cat
1: Keyboard Cat
1: New Cat

1: Keyboard Cat
1: Maru
1: Henri The Existential Cat
1: New Cat

But

1: Keyboard Cat
1: Keyboard Cat
1: Keyboard Cat
1: New Cat

1: Keyboard Cat
1: Keyboard Cat
1: Keyboard Cat
1: New Cat

Both render well. Can you give me an idea about it?

import { For, createSignal } from "solid-js";

const initialTodos = [
  {
    content: "TODO A",
    complete: true,
  },
  {
    content: "TODO B",
    complete: true,
  },
  {
    content: "TODO C",
    complete: true,
  },
];

function ForComp() {
  const [todos, setTodos] = createSignal(initialTodos);

  return (
    <For each={todos()}>
      {(todo, todoIdx) => {
        console.log("todo", todo, "todoIdx", todoIdx);

        return (
          <div>
            <h5
              style={{
                cursor: "pointer",
              }}
              onClick={() => {
                const newTodos = [...todos()];
                newTodos[todoIdx()] = {
                  ...newTodos[todoIdx()],
                  complete: !newTodos[todoIdx()].complete,
                };
                // newTodos.push({
                //   content: "TODO D",
                //   complete: false,
                // });
                setTodos(newTodos);
              }}
            >
              {todo.content}:{todo.complete.toString()}
            </h5>
          </div>
        );
      }}
    </For>
  );
}

function IndexComp() {
  const [todos, setTodos] = createSignal(initialTodos);

  return (
    <div>
      <Index each={todos()}>
        {(todo, todoIdx) => {
          console.log("todo", todo, "todoIdx", todoIdx);

          return (
            <div>
              <h5
                style={{
                  cursor: "pointer",
                }}
                onClick={() => {
                  const newTodos = [...todos()];
                  newTodos[todoIdx] = {
                    ...newTodos[todoIdx],
                    complete: !newTodos[todoIdx].complete,
                  };
                  // newTodos.push({
                  //   content: "TODO D",
                  //   complete: false,
                  // });
                  setTodos(newTodos);
                }}
              >
                {todo().content}:{todo().complete.toString()}
              </h5>
            </div>
          );
        }}
      </Index>
    </div>
  );
}

function App() {
  return (
    <>
      <h1>For</h1>
      <ForComp />
      <hr />
      <h1>Index</h1>
      <IndexComp />
    </>
  );
}

export default App;

In the above code, when I click an item of IndexComp, it renders correctly, but console.log doesn't print. I'm a bit confused about how the data is updated on the screen.

seongkuk han
  • 570
  • 6
  • 14

1 Answers1

0

You are rendering list of primitives that is why you have a hard time seeing the difference.

The difference is in rendering list of objects and how previously rendered list items are reused between update cycles.

Index uses index value as key for caching previously rendered items.

snnsnn
  • 10,486
  • 4
  • 39
  • 44