React Context API возвращает неопределенное - PullRequest
0 голосов
/ 24 апреля 2020

Я довольно новичок в React, и я пытаюсь создать ToDoList. У меня есть модал с кнопкой отправки, которая при нажатии должна добавить ToDoItem. Но так как я не хотел продвигаться дальше, я хотел использовать Context API. Context API меня немного смущает, может быть, я просто придурок, но мне трудно понять, почему я должен сделать ловушку и передать это как значение в провайдере. Я думал, что в ToDoContext я уже определил значение по умолчанию как пустой массив, поэтому я просто сделал это снова.

В консоли в строке 62, которая является моей первоначальной визуализацией, написано, что она не определена, после нажатия кнопки «Добавить задачу» я получаю то же сообщение. Showing my console after pressing the Add ToDo

App.jsx

import React, { useState } from "react";
import { render } from "react-dom";
import { ThemeProvider } from "emotion-theming";
import { defaultTheme } from "./theme";
import { Global, css } from "@emotion/core";
import Header from "./components/Header";
import ToDoList from "./components/ToDoList";
import AddBtn from "./components/AddBtn";
import ToDoContext from "./ToDoContext";

    const App = () => {
      const [toDoItems] = useState([]);

      return (
        <>
          {/*Global styling*/}
          <Global
            styles={css`
              * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
                list-style: none;
                text-decoration: none;
              }
            `}
          />

          {/*App render start from here*/}
          <ThemeProvider theme={defaultTheme}>
            <ToDoContext.Provider value={toDoItems}>
              <Header />
              <main>
                <ToDoList />
                <AddBtn />
              </main>
            </ToDoContext.Provider>
          </ThemeProvider>
        </>
      );
    };

    render(<App />, document.getElementById("root"));

ToDoContext.jsx

import { createContext } from "react";

const ToDoContext = createContext([[], () => {}]);

export default ToDoContext;

AddBtn.jsx

import React, { useState, useContext } from "react";
import { css } from "emotion";
import Modal from "../Modal";
import ToDoContext from "../ToDoContext";

const BtnStyle = css`
  position: fixed;
  bottom: 0;
  right: 0;
  cursor: pointer;
  display: block;
  font-size: 7rem;
`;

const ModalDiv = css`
  position: fixed;
  left: 50%;
  background-color: #e6e6e6;
  width: 60%;
  padding: 20px 20px 100px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 400px;
  height: 50%;
  transform: translate(-50%, -50%);
  border-radius: 20px;
  top: 50%;
`;

const textareaStyle = css`
  resize: none;
  width: 100%;
  height: 200px;
  font-size: 1.25rem;
  padding: 5px 10px;
`;

const timeStyle = css`
  font-size: 3rem;
  display: block;
`;

const modalSubmit = css`
  width: 100%;
  font-size: 3rem;
  cursor: pointer;
  margin-top: auto;
`;

const Label = css`
  font-size: 2rem;
  text-align: center;
  display: inline-block;
  margin-bottom: 50px;
`;

const AddBtn = () => {
  const [showModal, setShowModal] = useState(true);
  const [time, setTime] = useState("01:00");
  const [toDoItems, setToDoItems] = useContext(ToDoContext);
  console.log(toDoItems);
  return (
    <>
      <div className={BtnStyle} onClick={() => setShowModal(!showModal)}>
        <ion-icon name="add-circle-outline"></ion-icon>
      </div>

      {showModal ? (
        <Modal>
          <div className={ModalDiv}>
            <div>
              <label className={Label} htmlFor="time">
                Time
                <input
                  className={timeStyle}
                  type="time"
                  name="time"
                  value={time}
                  onChange={(e) => setTime(e.target.value)}
                />
              </label>
            </div>
            <label className={Label} htmlFor="desc">
              Description
              <textarea
                className={textareaStyle}
                name="desc"
                placeholder={`Notify yourself this message in ${time}`}
              ></textarea>
            </label>
            <button
              className={modalSubmit}
              onClick={() => {
                setToDoItems(
                  toDoItems.push({
                    time,
                  })
                );
              }}
            >
              Add ToDo
            </button>
          </div>
        </Modal>
      ) : null}
    </>
  );
};

export default AddBtn;

1 Ответ

2 голосов
/ 24 апреля 2020

В вашем коде есть несколько проблем, которые нужно исправить:

  • useState возвращает value и setter. С этой строкой кода, const [toDoItems] = useState([]);, вы просто передаете пустой массив вашему контексту.

Сделайте так:

const toDoItems = useState([]);
  • В вашем ToDoContext. js просто передайте пустой массив в качестве аргумента (начальное значение)
const ToDoContext = createContext([]);

Рабочая копия вашего кода находится здесь . (см. журналы консоли)

Также я заметил, что вы вводите задачу в setTodoItems в AddBtn. js.

Не делайте этого:

onClick={() => {
                setToDoItems(
                  toDoItems.push({
                    time
                  })
                );
              }}

Сделайте это:

onClick={() => {
                setToDoItems(
                  toDoItems.concat([
                    {
                      time
                    }
                  ])
                );
              }}
...