【问题标题】:sveltekit: component is not being rendered second time though the URL has been changedsveltekit:尽管 URL 已更改,但组件未第二次呈现
【发布时间】:2021-10-25 12:53:24
【问题描述】:

我是 sveltekit 的新手。

我有一个页面 [symbol].svelte。

http://localhost:3000/stocks/mnr-pc = host/stocks/[符号]

当 URL 的符号发生变化时,它应该从 API 获取该符号的数据并将数据作为道具传递给子组件。

要更改 slug/符号,我在页面顶部有一个搜索框。我搜索一个符号,当我从搜索框中单击任何符号时,我更改了 url。

例如:如果我选择符号“tsla”,我将 URL 更改为 http://localhost:3000/stocks/tsla。

问题是,在第一次更改 URL 时,它从 API 中获取数据,并通过子组件显示数据。但是之后,如果我再次搜索一个新符号并单击它,虽然路由器发生了变化,但 UI 上的数据仍然保持不变。

[symbol].svelte此文件位于 routes/stocks 文件夹中

<script context="module">
    import StockSymbol from '$lib/stocks/index.svelte';
    import data from '../../../static/symbols.json';

    let props;
    let symbolName;
    export const hydrate = true

    export async function load({ page, fetch }) {
        symbolName = page.params.symbol;
        let symbols = data.symbols;
        let symbolFound = symbols.find(s => s.s.toLowerCase() === page.params.symbol.toLowerCase());

        if (!symbolFound) {
            return {
                status: 302,
                redirect: '/404'
            }
        }

        const url = `APIHOST/${symbolName}`;
        const res = await fetch(url);
        let stock = await res.json();
        stock = stock.data.attributes;

        props = {
            stock
        };

        return {
            props: {
                stock
            }
        }
    }
</script>

<svelte:head>
    <title>Stock: { symbolName || ''}</title>
</svelte:head>

<svelte:component this={StockSymbol} {...props}/>

search.svelte

<script context="module">
    import AutoComplete from "simple-svelte-autocomplete";
    import data from '../../../static/symbols.json';
    import { goto, prefetch } from '$app/navigation';

    var options = data;
    let selectedOption;

    const handleOnChange = () => {
        console.log(selectedOption);
        if (selectedOption) {
            goto(`/stocks/${selectedOption.s.toLowerCase()}`, {replaceState: true});
        }
    }
</script>

<div class="min-w-0 hidden sm:block flex-1 md:px-8 lg:px-48 xl:col-span-6">
    <div class="flex items-center px-6 py-4 md:max-w-3xl md:mx-auto lg:max-w-none lg:mx-0 xl:px-0">
        <div class="w-full">
            <label for="search" class="sr-only">Search</label>
            <div class="relative">
                <div class="z-20 pointer-events-none absolute inset-y-1 left-0 pl-3 flex items-center">
                    <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                        <path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"></path>
                    </svg>
                </div>
                <AutoComplete 
                    onChange={handleOnChange}
                    inputId="search" 
                    placeholder="Search" 
                    className="w-full text-md"
                    inputClassName="block px-10 py-2 w-full rounded-md border border-gray-300 text-sm placeholder-gray-500 focus:outline-none focus:text-gray-900 focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" 
                    items={data.symbols.map(o => o)} 
                    labelFunction={o => o.s + '. ' + o.n}
                    bind:selectedItem={selectedOption} 
                    hideArrow={true}
                    showClear={true}
                    showLoadingIndicator={true}
                    noResultsText="No Results Found"
                    maxItemsToShowInList="10"
                    localFiltering=false 
                />
            </div>
        </div>
    </div>
</div>

svelte.config.js

import vercel from '@sveltejs/adapter-vercel';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    kit: {
        target: '#app',
        adapter: vercel(),
        hydrate: true,
        vite: {
            build: {
                minify: true,
                brotliSize: true,
                sourcemap: true,
            }
        }
    }
};

export default config;

请帮帮我。谢谢。

【问题讨论】:

    标签: javascript svelte sveltekit


    【解决方案1】:

    您在模块脚本中声明props 并在load 函数中分配它。这只适用于第一次。 Svelte explicitely states in its docs 模块脚本内的变量更新不是反应性的。解决的方法是明确声明道具(首选方式)或使用$$restProps

    <script context="module">
        //...
        // Do NOT declare "let props" here
    
        export async function load({ page, fetch }) {
            // ..
    
            return {
                props: {
                    stock // <- handed to the instance script
                }
            }
        }
    </script>
    
    <script>
        export let stock; // <- this gets the stock from "return { props: { stock } }" above
    </script>
    ..
    <svelte:component this={StockSymbol} {stock}/>
    <!-- or (then you don't need the "export let stock" abive) -->
    <svelte:component this={StockSymbol} {...$$restProps}/>
    

    【讨论】:

    • 感谢您的回答。我只是按照您的解决方案进行操作,但不起作用。同样的问题。第二次组件不渲染。
    • 还有一件事是,在第二个
    • 你需要启动一个计时器,在 DOM 更新之前,它不会重新加载。相同的页面元素需要刷新或页面更改后,需要在 3 秒或 3 秒内反应
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2023-03-28
    • 2019-11-30
    • 2021-12-22
    • 2018-02-21
    • 2019-08-18
    • 2019-11-23
    相关资源
    最近更新 更多