Reactjs React上下文API返回未定义的

Reactjs React上下文API返回未定义的,reactjs,react-hooks,context-api,Reactjs,React Hooks,Context Api,我是一个新的反应者,我正试图成为一个托德主义者。我有一个带有提交按钮的模式,按下该按钮时应添加一个ToDoItem。但是,由于我不想通过这种方式进行钻取,所以我想使用上下文API。上下文API让我有点困惑,也许我只是个白痴,但我很难理解为什么我必须创建一个钩子并将其作为值传递给提供者。我认为在ToDoContext中,我已经将默认值定义为空数组,所以我只是再次这样做 在控制台的第62行,这是我的初始渲染,它说它是未定义的,在按下addtodo之后,我得到了相同的消息。 App.jsx impo

我是一个新的反应者,我正试图成为一个托德主义者。我有一个带有提交按钮的模式,按下该按钮时应添加一个ToDoItem。但是,由于我不想通过这种方式进行钻取,所以我想使用上下文API。上下文API让我有点困惑,也许我只是个白痴,但我很难理解为什么我必须创建一个钩子并将其作为值传递给提供者。我认为在ToDoContext中,我已经将默认值定义为空数组,所以我只是再次这样做

在控制台的第62行,这是我的初始渲染,它说它是未定义的,在按下addtodo之后,我得到了相同的消息。

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"));
import { createContext } from "react";

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

export default ToDoContext;
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;
AddBtn.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"));
import { createContext } from "react";

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

export default ToDoContext;
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;
import React,{useState,useContext}来自“React”;
从“情感”中导入{css};
从“./Modal”导入模态;
从“./ToDoContext”导入ToDoContext;
常量BtnStyle=css`
位置:固定;
底部:0;
右:0;
光标:指针;
显示:块;
字体大小:7rem;
`;
常量ModalDiv=css`
位置:固定;
左:50%;
背景色:#e6;
宽度:60%;
填充:20px 20px 100px 20px;
显示器:flex;
弯曲方向:立柱;
对齐项目:居中;
最大宽度:400px;
身高:50%;
转换:翻译(-50%,-50%);
边界半径:20px;
最高:50%;
`;
const textraestyle=css`
调整大小:无;
宽度:100%;
高度:200px;
字体大小:1.25rem;
填充物:5px10px;
`;
const timeStyle=css`
字体大小:3rem;
显示:块;
`;
const modalSubmit=css`
宽度:100%;
字体大小:3rem;
光标:指针;
页边顶部:自动;
`;
常量标签=css`
字号:2rem;
文本对齐:居中;
显示:内联块;
边缘底部:50px;
`;
常量AddBtn=()=>{
const[showmodel,setshowmodel]=useState(true);
常数[时间,设置时间]=使用状态(“01:00”);
const[toDoItems,setToDoItems]=useContext(ToDoContext);
console.log(toDoItems);
返回(
设置showModal(!showModal)}>
{showModal(
时间
设置时间(e.target.value)}
/>
描述
{
setToDoItems(
推({
时间
})
);
}}
>
添加待办事项
):null}
);
};
导出默认AddBtn;

代码中有几个问题需要解决:

  • useState
    返回一个
    和一个
    设置器
    。对于这行代码,
    const[toDoItems]=useState([]),您只是将一个空数组传递给您的上下文
这样做:

const toDoItems=useState([]);
  • 在ToDoContext.js中,只需传递一个空数组作为参数(初始值)
const ToDoContext=createContext([]);
你的工作副本。(请参阅控制台日志)

另外,我注意到您正在AddBtn.js中的
setTodoItems
中推送todo

不要这样做:

onClick={()=>{
setToDoItems(
推({
时间
})
);
}}
这样做:

onClick={()=>{
setToDoItems(
海螺([
{
时间
}
])
);
}}

代码中有几个问题需要解决:

  • useState
    返回一个
    和一个
    设置器
    。对于这行代码,
    const[toDoItems]=useState([]),您只是将一个空数组传递给您的上下文
这样做:

const toDoItems=useState([]);
  • 在ToDoContext.js中,只需传递一个空数组作为参数(初始值)
const ToDoContext=createContext([]);
你的工作副本。(请参阅控制台日志)

另外,我注意到您正在AddBtn.js中的
setTodoItems
中推送todo

不要这样做:

onClick={()=>{
setToDoItems(
推({
时间
})
);
}}
这样做:

onClick={()=>{
setToDoItems(
海螺([
{
时间
}
])
);
}}

希望答案有帮助。。。如果你有任何问题,请告诉我。。。谢谢你的帮助,但是我仍然不确定为什么推送是错误的。toDoItems是一个数组,所以我将新值设置为原始数组+将新数组推入其中。是因为你不能用第一个arr的新值更新状态吗?不管怎样,我找到了一篇很好的文章来解释它。希望答案有帮助。。。如果你有任何问题,请告诉我。。。谢谢你的帮助,但是我仍然不确定为什么推送是错误的。toDoItems是一个数组,所以我将新值设置为原始数组+将新数组推入其中。是因为你不能用第一个arr的新值更新状态吗?不管怎样,我找到了一篇很好的文章来解释它。