React Hooks - TypeError: Невозможно установить свойство isCompleted из неопределенного - PullRequest
0 голосов
/ 10 марта 2020

Постоянно получаю ошибку типа в моем приложении todo. Я пытаюсь установить для свойства isComplete значение true.

Ошибка: TypeError: Cannot set property 'isCompleted' of undefined

My complete_todo. js Файл:

import { TodoContext } from './todo_ctx'; 


const MarkComplete = (index) => {
    const [tasks, setTodos] = useContext(TodoContext);

        const newTask = [...tasks];
        newTask[index].isCompleted = true;
        setTodos(newTask);

    return (
        <button onClick={MarkComplete}>Mark Complete</button>
    );
}

export default MarkComplete;

My todo_ctx. js file:

import React, { useState, createContext} from 'react';

export const TodoContext = createContext();

export const TodoProvider = (props) => { 
    const [tasks, setTodos] = useState([
        {
            id: 1,
            task: 'Learn React',
            description: 'Build a todo app in React',
            isCompleted: false
        },
        {
            id: 2,
            task: 'Learn Node',
            description: 'Build a Node API',
            isCompleted: false
        },
        {
            id: 3,
            task: 'Learn Flutter',
            description: 'Complete Flutter Course',
            isCompleted: false
        }
    ]);

    return (
        <TodoContext.Provider value={[tasks, setTodos]}>
            {props.children}
        </TodoContext.Provider>
    )
}

Я новичок в React, мне здесь чего-то не хватает ??

Ответы [ 3 ]

0 голосов
/ 10 марта 2020

Вы завернули свое приложение, используя своего провайдера ???

Пример:

import { TodoProvider } from "./src/context/todo_ctx.js";

const App = createAppContainer(navigator);
export default () => {
  return (
    <TodoProvider>
      <App />
    </TodoProvider>
  );
};
0 голосов
/ 10 марта 2020

Так что я не думаю, что вам нужен контекст, особенно то, как вы его используете. Я попробовал это для вас, позвольте мне знать, поможет ли это:

import React, { useState } from "react";

const Todos = () => {
  const [tasks, setTodos] = useState([
    {
      id: 1,
      task: "Learn React",
      description: "Build a todo app in React",
      isCompleted: false
    },
    {
      id: 2,
      task: "Learn Node",
      description: "Build a Node API",
      isCompleted: false
    },
    {
      id: 3,
      task: "Learn Flutter",
      description: "Complete Flutter Course",
      isCompleted: false
    }
  ]);

  const setTodoHelper = taskId => {
    setTodos(
      tasks.map(x =>
        x.id === taskId ? { ...x, isCompleted: !x.isCompleted } : x
      )
    );
  };

  return (
    <>
      {tasks.map(task => (
        <Todo key={task.id} {...task} setTodoHelper={setTodoHelper} />
      ))}
    </>
  );
};

const Todo = ({ id, setTodoHelper, isCompleted }) => {
  return (
    <>
      <div>{id}</div>
      <div>completed: {String(isCompleted)} </div>
      <button onClick={() => setTodoHelper(id)}>Mark Complete</button>
    </>
  );
};

export default Todos;

ref: https://codesandbox.io/s/cranky-pond-x96sy

0 голосов
/ 10 марта 2020

В вашем коде есть несколько ошибок.

  1. Потребитель должен быть дочерним элементом поставщика контекста.
  2. Обновляя состояние непосредственно в теле компонента, вы должны обновить состояние внутри hook или function.
  3. При нажатии кнопки вы вызываете сам компонент, который является неправильным.
  4. Вместо этого, если передать index, вы можете передать задачу.

Я сделал некоторые изменения в вашем коде, пожалуйста попробуйте.

import React, { useState, createContext, useContext, Component } from 'react';
import './App.css';

export const TodoContext = createContext();
export const TodoProvider = (props) => {
  const [tasks, setTodos] = useState([
    {
      id: 1,
      task: 'Learn React',
      description: 'Build a todo app in React',
      isCompleted: false
    },
    {
      id: 2,
      task: 'Learn Node',
      description: 'Build a Node API',
      isCompleted: false
    },
    {
      id: 3,
      task: 'Learn Flutter',
      description: 'Complete Flutter Course',
      isCompleted: false
    }
  ]);
  return (
    <TodoContext.Provider value={[tasks, setTodos]}>
      <MarkComplete />
    </TodoContext.Provider>
  )
}

const MarkComplete = (props) => {
  const [tasks, setTodos] = useContext(TodoContext);

  function todoHandler(taskId) {
    const newTask = tasks.map(task => {
      if (task.id === taskId) {
        task.isCompleted = !task.isCompleted;
      }
      return task;
    });
    setTodos(newTask);
  }

  return (
    <div >
      <table>
        <thead>
          <tr>
            <th>Task Id</th>
            <th>Task</th>
            <th>isCompleted</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {tasks.map(task => (
            <tr key={task.id}>
              <td>{task.id}</td>
              <td>{task.task}</td>
              <td>{String(task.isCompleted)}</td>
              <td><button onClick={() => todoHandler(task.id)}>Mark Complete ({task.id})</button></td>
            </tr>
          ))}
        </tbody>

      </table>
    </div>

  );
}




function App() {

  return <TodoProvider />
}
export default App;


Codesandbox Link:

Edit nervous-tdd-y2y43

...