英文:
Is this normal that each list item in Solidjs is mounting on every change?
问题
在 Solidjs 中,每次更改时每个列表项都会挂载,这是正常的吗?
import { Component, createSignal, For } from 'solid-js';
const data = [
{name: 'Helen'},
{name: 'Peter'},
{name: 'Maksim'},
]
const Card: Component = (props: {name: string}) => {
console.log('card'); // 它在每次点击时运行,这不是我预期的
return <div>
<span>姓名:</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'})))}>点击</button>
<For each={users()}>{user => <Card {...user} />}</For>
</>
);
};
对于 createStore 也是一样的情况。
英文:
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.
答案1
得分: 1
这是正常的,因为您正在通过在setUsers
上映射项目并创建具有相同值的新对象来更新setUsers
中的每个列表项。尽管您使用先前的值,但您正在创建新对象。
For
保留项目的引用,如果数组项不更改。它的内部逻辑类似于这样:
const cache = {};
cache[user] = <Card />
由于您正在更改每个数组项,通过丢弃旧键来使缓存无效,因此将呈现新项目。当呈现此新项目时,Card
被挂载。
尝试这段代码,在这个代码中,我们只更新了第一个项目:
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);
英文:
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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论