Что вызывает ошибку «ctx[1] не является функцией» в этом небольшом изящном приложении?

#javascript #svelte

Вопрос:

Я работаю над небольшим приложением для работы со стройностью. Я перечисляю 10 задач из jsonplaceholder.

У меня есть это в приложении.стройная:

 <script>
    import { onMount } from "svelte";
    import Header from './Header.svelte';
    import ToDoList from './ToDoList.svelte';
    import Footer from './Footer.svelte';
    const apiURL = "https://jsonplaceholder.typicode.com/todos";
    const limit = 10;
    let todos = [];
    export let unsolvedTodos = [];
    
    onMount(() => {
        getTodos();
    });
    
    const getTodos = () => {
        fetch(`${apiURL}?amp;_limit=${limit}`)
        .then(res => res.json())
        .then((data) => todos = data)
        .then(getUnsolvedTodos);
    }
    
    const getUnsolvedTodos = () => {
        unsolvedTodos = todos.filter(todo => {
            return todo.completed === false;
        })
    }

    const deleteTodo = (todo) => {
        let itemIdx = todos.findIndex(x => x == todo);
        todos.splice(itemIdx, 1);
        todos = todos;
  }
</script>

<div class="app-wrapper">
  <div id="toDoApp">
        <Header />
    <ToDoList todos={todos} />
    <Footer />
  </div>
</div>
 

В приложении ToDoList.app:

 <script>
    import TodoItem from './TodoItem.svelte';
    export let todos;
    let deleteTodo;
</script>

{#if todos.length > 0}
  <ul class="todo-list">
    {#each todos as todo, index}
        <TodoItem {todo} on:deleteTodo = {deleteTodo(todo)} />
    {/each}
  </ul>
{/if}
 

В TodoItem.стройная:

 <script>
    import {createEventDispatcher} from 'svelte';
    import { fade, fly } from 'svelte/transition';
    import { flip } from 'svelte/animate';
    export let todo;
    
    const dispatch = createEventDispatcher();
    const Delete = () => dispatch("deleteTodo", todo);
</script>

<li transition:fly="{{x:-100, duration:200}}">
    <input type="checkbox" checked="{todo.completed}" />
    <span class="title {todo.completed ? 'done' : ''}">{todo.title}</span>
    <button on:click="{Delete}"><i class="fa fa-trash" aria-hidden="true"></i></button>
</li>
 

Должно быть, я что-то упускаю, потому что я получаю ошибку ctx[1] is not a function , как видно из этого повторения.

Что я делаю не так?

Ответ №1:

В ToDoList.svelte вы звоните deleteTodo(todo) , но deleteTodo не определено. Стройный действительно должен выдать здесь лучшее сообщение об ошибке…

Редактировать:

Кроме того, если вы назначаете обработчик событий, вы хотите передать ссылку на функцию типа on:deleteTodo = {() => deleteTodo(todo)} или on:deleteTodo = {deleteTodo} , а не вызывать функцию напрямую.

Комментарии:

1. У меня let deleteTodo в Тодолисте.стройная, наверху. У меня тоже есть <TodoItem {todo} on:deleteTodo = {deleteTodo(todo)} /> . См. РЕПЛ .

2. У вас есть let deleteTodo , но это переменная, а не определение функции, поэтому ничего не происходит, когда вы вызываете ее как функцию. Кроме того, как сказал Леандер, вы неправильно называете это, если хотите передать аргумент функции с помощью обработчика событий, он не будет работать так, как {function(arg)} вам нужно {()=> function(arg)} . Этот ответ верен.

3. Может быть, вы хотите передать deleteTodo функцию, которая объявлена в App.svelte to ToDoList . so let deleteTodo; , должна стать export let deleteTodo; и <ToDoList todos={todos} /> может стать <ToDoList todos={todos} deleteTodo={deleteTodo} /> или сокращением <ToDoList {todos} {deleteTodo} /> . Это не лучший образец для подражания, но он работает