Trouble accessing context values with useContext in child component

I am making Google Keep Clone with React and Context API (useContext hook). It was going very smoothly, everything was coming in proper order until I thought of somehow passing the notes from home to the archive and delete section using a button. For this purpose, I have used the useContext hook so that I can avoid unnecessary prop drilling and complex codes. But somehow it’s not working. Can anyone help me?

import React, { createContext, useState } from "react";
export const dataContext = createContext([]);

const Context = ({ children }) => {
  const [addData, setAddData] = useState([]); //to store all the values of the state data
  const [archive, setArchive] = useState([]);
  const [deleteNotes, setDeleteNotes] = useState([]);

  return (
    <>
      <dataContext.Provider
        value={{
          addData,
          setAddData,
          archive,
          setArchive,
          deleteNotes,
          setDeleteNotes,
        }}
      >
        {children}
      </dataContext.Provider>
    </>
  );
};

export default Context;
// export { dataContext };
import React, { useContext, useState } from "react";
import Inputbox from "../Components/Inputbox";
import { dataContext } from "../Components/Context";
import { v4 as uuid } from "uuid";
import SingleNote from "../Components/SingleNote";

const Notes = () => {
  const [loading, setLoading] = useState(true);
  const { addData, setAddData, setArchive, setDeleteNotes } =
    useContext(dataContext);
  //Math.random can also be used here but to make things simpler we have used an npm package as we don't know how many notes a person will save
  const [show, setShow] = useState(false); //to toggle between the main note and the big note

  const [data, setData] = useState({
    //to stores all the values given by the user
    id: uuid(),
    title: "",
    description: "",
  });

  const addNote = () => {
    setAddData((oldData) => {
      return [...oldData, data]; // Calling the done function using the addNote function
    });
  };

  const Delete = (index) => {
    const DelArray = addData.filter((Val) => {
      return index !== Val.id;
    });
    setAddData(DelArray);
    setDeleteNotes((preArr) => [addData, ...preArr]);
  };

  const Archive = (index) => {
    const ArchiveArray = addData.filter((Val) => {
      return index !== Val.id;
    });
    setAddData(ArchiveArray);
    setArchive((preArr) => [addData, ...preArr]);
  };

  const handleClickAway = (e, val) => {
    e.preventDefault();
    setShow(false); //if the data filed is blank, close the input fields
    //if the data field is not empty
    if (data.title || data.description) {
      setLoading(false);
      addNote(val);
      setData({
        title: "",
        description: "",
      });
    }
  };
  return (
    <>
      <Inputbox
        handleClickAway={handleClickAway}
        data={data}
        setData={setData}
        setAddData={setAddData}
        show={show}
        setShow={setShow}
      />
      {loading ? (
        <div style={{ marginLeft: "30%", marginTop: "5%" }}>
          <div className="icon-1">
            <i class="fa-regular fa-note-sticky"></i>
          </div>
          <div className="fs-3 fw-bold opacity-50">
            Your Notes will Appear Here
          </div>
        </div>
      ) : (
        <SingleNote addData={addData} Delete={Delete} Archive={Archive} />
      )}
    </>
  );
};

export default Notes;
import React from "react";

const SingleNote = ({ addData, Delete, Archive }) => {
  return (
    <>
      <div className="row mt-5 d-flex">
        {addData &&
          addData.map((Val, index) => {
            const { title, description, id } = Val;
            return (
              <>
                <div className="note m-3" key={index} id={index}>
                  <div className="fs-4 fw-bold">{title}</div>
                  <br />
                  <p>{description}</p>
                  <div className="d-flex flex-row-reverse">
                    <div
                      onClick={() => Delete(id)}
                      style={{ cursor: "pointer" }}
                      title="Delete"
                    >
                      <i className="fa-regular fa-trash-can fs-4 py-2 text-danger mx-3"></i>
                    </div>
                    <div
                      onClick={() => Archive(id)}
                      style={{ cursor: "pointer" }}
                      title="Archive"
                    >
                      <i className="fa-solid fa-boxes-stacked fs-4 py-2 text-success"></i>
                    </div>
                  </div>
                </div>
              </>
            );
          })}
      </div>
    </>
  );
};

export default SingleNote;
import React, { useContext } from "react";
import { dataContext } from "../Components/Context";

const Archive = () => {
  const { archive, setAddData, setArchive, setDeleteNotes } =
    useContext(dataContext);

  const Delete = (index) => {
    const DelArray = archive[0].filter((Val) => {
      return index !== Val.id;
    });
    setDeleteNotes(DelArray);
    setAddData((preArr) => [archive, ...preArr]);
  };

  const UnArchive = (index) => {
    const ArchiveArray = archive[0].filter((Val) => {
      return Val.id !== index;
    });
    setArchive(ArchiveArray);
    setAddData((preArr) => [...preArr, archive]);
  };
  return (
    <>
      <div className="row mt-5 d-flex">
        {archive.map((Val, index) => {
          const entry = Val[0];
          const { title, description, id } = entry;
          return (
            <>
              <div className="note m-3" key={index} id={index}>
                <div className="fs-4 fw-bold">{title}</div>
                <br />
                <p>{description}</p>
                <div className="d-flex flex-row-reverse">
                  <div
                    onClick={() => Delete(id)}
                    style={{ cursor: "pointer" }}
                    title="Delete"
                  >
                    <i className="fa-regular fa-trash-can fs-4 py-2 text-danger mx-3"></i>
                  </div>
                  <div
                    onClick={() => UnArchive(id)}
                    style={{ cursor: "pointer" }}
                    title="Unarchive"
                  >
                    <i className="fa-solid fa-arrow-up-from-ground-water fs-4 py-2 text-success"></i>
                  </div>
                </div>
              </div>
            </>
          );
        })}
      </div>
    </>
  );
};

export default Archive;

Now the problem that I am facing is I can send the data from the notes component to the archive component, but it’s not coming back from the archive component to the notes component. PLease help me.

You are more likely to get help if you post a GitHub repo or a StackBlitz/CodeSandbox.

Github repo - GitHub - Ateevduggal/google-keep-clone: An app that closely resembles Google Keep with most of its features and UI

Try logging out what Val is inside the delete filter.

For dynamic lists, it is important to use the key prop correctly. You have unnecessary fragments <></> some of which should have been elements with a key prop.

Code and test the app with the browser console open.


I think your state management is quickly going to get confusing the way it is now. I would suggest looking at useReducer, or small state management lib, e.g. Zustand. It will make the state more manageable and the shape of the state will be easier to reason about.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.