![](/img/trans.png)
[英]How do I update the state to force a rerender if my props change in React?
[英]How do I force a rerender in Svelte when my props changes?
我有一個總計組件需要在多維數組中總計多個 arrays 的相同索引,類似於電子表格中的總計列。 我有一個不同的組件,它允許我更改 arrays 中的值,並匯總電子表格中的行。 我在對數組進行更改后重新渲染和/或更新列總數時遇到問題。 我想我可能需要在我的總計組件中做一個反應性聲明,但這似乎不起作用。
這是代碼:
Totals.svelte
<script>
export let jobs
//this creates a new array which is two indexes long for each of the columns
//then fills each array with the sum of column
//HOW DO I GET THIS TO UPDATE EACH TIME A JOB HOURS ENTRY IS CHANGED?
$: totals = new Array(2).fill(null).map((v, i) => {
let total = 0;
jobs.jobHours.forEach((v) => {
total += Number(v[i]);
});
return total;
});
//this sums the total hours row to give the grand total
//HOW DO I GET THIS TO UPDATE EACH TIME THE TOTALS VARIABLE IS CHANGED?
$: grandTotal = totals.reduce((acc, v) => (acc += v));
</script>
<style>
container {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
}
div {
width: 100%;
height: 100%;
width: 150px;
}
</style>
<container>
<div>Total Hours</div>
{#each totals as total}
<div>
{total}
</div>
{/each}
<div>{grandTotal}</div>
</container>
App.svelte
<script>
import JobEntries from './JobEntries.svelte';
import Totals from './Totals.svelte';
const jobs = {
jobNames: ['Job1', 'Job2', 'Job3'],
jobHours: Array.from(Array(3), () => Array.from(Array(2), ()=>1))
};
</script>
<JobEntries {jobs}/>
<Totals {jobs} />
JobEntries.svelte
<script>
export let jobs
let cell = Array.from(Array(3), () => Array.from(Array(3)));
</script>
<style>
container {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
}
input, div {
width: 100%;
height: 100%;
min-width: 150px;
}
</style>
<container>
<div>
Name
</div>
<div>
Time 1
</div>
<div>
Time 2
</div>
<div>
Total
</div>
{#each jobs.jobNames as name, i}
<input
type="text"
bind:this={cell[i][0]}
bind:value={name} />
{#each jobs.jobHours[i] as hour, j}
<input
type="number"
bind:this={cell[i][j+1]}
bind:value={hour}
/>
{/each}
<div>
{jobs.jobHours[i].reduce((acc,v)=>acc+=v)}
</div>
{/each}
</container>
在父組件中綁定 prop,允許子組件更改 prop。
App.svelte
<script>
import JobEntries from './JobEntries.svelte';
import Totals from './Totals.svelte';
let jobs = {
jobNames: ['Job1', 'Job2', 'Job3'],
jobHours: Array.from(Array(3), () => Array.from(Array(2), ()=>1))
};
</script>
<JobEntries bind:jobs/>
<Totals {jobs} />
JobEntries.svelte
<script>
export let jobs
let cell = Array.from(Array(3), () => Array.from(Array(3)));
</script>
<style>
container {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
}
input, div {
width: 100%;
height: 100%;
min-width: 150px;
}
</style>
<container>
<div>
Name
</div>
<div>
Time 1
</div>
<div>
Time 2
</div>
<div>
Total
</div>
{#each jobs.jobNames as name, i}
<input
type="text"
bind:this={cell[i][0]}
bind:value={name} />
{#each jobs.jobHours[i] as hour, j}
<input
type="number"
bind:this={cell[i][j+1]}
bind:value={hour}
/>
{/each}
<div>
{jobs.jobHours[i].reduce((acc,v)=>acc+=v)}
</div>
{/each}
</container>
Alexander 的評論讓我想到了App.svelte
中的jobs
實際上並未更新,以及我如何才能做到這一點。 使用 Svelte 的event dispatch
,我可以讓子組件將更新的 prop 發送回父組件,並在收到消息后更新App.svelte
中的jobs
。 雖然我同意 Svelte 商店可能是處理 state 的更好方法,但這個問題可以在沒有商店的情況下解決。 下面是代碼。
App.svelte
<script>
import JobEntries from './JobEntries.svelte';
import Totals from './Totals.svelte';
const jobs = {
jobNames: ['Job1', 'Job2', 'Job3'],
jobHours: Array.from(Array(3), () => Array.from(Array(2), ()=>1))
};
</script>
<JobEntries {jobs} on:message={e=>jobs.jobHours = e.detail}/>
<Totals {jobs} />
JobEntries.svelte
<script>
import { createEventDispatcher } from 'svelte';
export let jobs
const dispatch = createEventDispatcher();
let cell = Array.from(Array(3), () => Array.from(Array(3)));
</script>
<style>
container {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
}
input, div {
width: 100%;
height: 100%;
min-width: 150px;
}
</style>
<container>
<div>
Name
</div>
<div>
Time 1
</div>
<div>
Time 2
</div>
<div>
Total
</div>
{#each jobs.jobNames as name, i}
<input
type="text"
bind:this={cell[i][0]}
bind:value={name} />
{#each jobs.jobHours[i] as hour, j}
<input
type="number"
bind:this={cell[i][j+1]}
bind:value={hour}
on:input={e=>dispatch('message', jobs.jobHours)}
/>
{/each}
<div>
{jobs.jobHours[i].reduce((acc,v)=>acc+=v)}
</div>
{/each}
</container>
Totals.svelte
<script>
export let jobs
//this creates a new array which is two indexes long for each of the columns
//then fills each array with the sum of column
$: totals = new Array(2).fill(null).map((v, i) => {
let total = 0;
jobs.jobHours.forEach((v) => {
total += Number(v[i]);
});
return total;
});
//this sums the total hours row to give the grand total
$: grandTotal = totals.reduce((acc, v) => (acc += v));
</script>
<style>
container {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
}
div {
width: 100%;
height: 100%;
width: 150px;
}
</style>
<container>
<div>Total Hours</div>
{#each totals as total}
<div>
{total}
</div>
{/each}
<div>{grandTotal}</div>
</container>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.