i was just following a react course about Context API i don't know if they have introduced any new syntax?if so please do say the error is "context is not iterable TypeError: context is not iterable"
Here is the app.js:---
just imported react router and the context function(NoteState)
import './App.css';
import About from "./components/About"
import Navbar from "./components/Navbar"
import Home from "./components/Home"
import {
BrowserRouter as Router,
Routes,
Route
} from "react-router-dom";
import NoteState from './context/notes/NoteState';
function App() {
return (
<>
<NoteState>
<Router>
<Navbar title="InoteBook"/>
<div className="container">
<Routes>
<Route path="/about" element={<About/>}/>
<Route path="/" element={<Home/>}/>
</Routes>
</div>
</Router>
</NoteState>
</>
);
}
export default App;
here is the notecontext:--
pretty simple just creating a new context and exporting it
import { createContext } from "react";
const noteContext = createContext();
export default noteContext;
Here is the main NoteState file:---
just hard coded some notes from my mongodb document and used it as the context
import { useState } from "react";
import NoteContext from "./notecontext";
const NoteState = (props)=>{
const notesInitial =[{
"_id": "6470a303fca0259ac90f3bbd",
"user": "646b656de67a029e93797b15",
"title": "binod",
"description": "binod binod binod",
"tag": "binod",
"date": "2023-05-26T12:16:03.400Z",
"__v": 0
},
{
"_id": "6470a31efca0259ac90f3bbf",
"user": "646b656de67a029e93797b15",
"title": "binodbinodbinod",
"description": "binod binod binod binod binod",
"tag": "binod binod binod",
"date": "2023-05-26T12:16:30.130Z",
"__v": 0
}]
const [notes,setNotes] = useState(notesInitial)
return(
<NoteContext.Provider value={{notes, setNotes}}>
{props.children}
</NoteContext.Provider>
)
}
export default NoteState
here is the Home.js component:---
main parts have arrows at the beginning
import React from "react";
import noteContext from "../context/notes/notecontext";
import { useContext } from "react";
const Home = (props) => {
> const context = useContext(noteContext)
> const [notes,setNotes] = context
return (
<>
<div className="container my-3">
<h2>Add a note</h2>
<form className="my-3">
<div className="mb-3">
<label for="exampleInputEmail1" className="form-label">
Email address
</label>
<input
type="email"
className="form-control"
id="exampleInputEmail1"
aria-describedby="emailHelp"
/>
<div id="emailHelp" className="form-text">
We'll never share your email with anyone else.
</div>
</div>
<div className="mb-3">
<label for="exampleInputPassword1" className="form-label">
Password
</label>
<input
type="password"
className="form-control"
id="exampleInputPassword1"
/>
</div>
<div className="mb-3 form-check">
<input
type="checkbox"
className="form-check-input"
id="exampleCheck1"
/>
<label className="form-check-label" for="exampleCheck1">
Check me out
</label>
</div>
<button type="submit" className="btn btn-primary">
Submit
</button>
</form>
</div>
> <div className="container my-3">
> <h2>Your Notes</h2>
>
> {notes.map((note)=>{
> return(note.title)
> })}
> </div>*
</>
);
};
export default Home;
Your issue is with const [notes,setNotes] = context
. Here you're using array destructuring syntax on context
which is an object, which by default aren't iterable so the syntax throws an error. For object destructuring, you need to destructure your object properties like so:
const {notes,setNotes} = context;
Alternatively, you can pass an array to your provider instead:
<NoteContext.Provider value={[notes, setNotes]}>
As arrays are iterable, the destructuring syntax that you had originally with [
and ]
will work in this case.
As a side note, you might want to memoize your context value to avoid recreating it on every rerender, and instead only create a new object/array when needed. Below is an example for creating an object:
const memoizedValue = useMemo(() => ({notes, setNotes}), [notes]); // when notes changes create a new object with the new note
<NoteContext.Provider value={memoizedValue}>
Above we're passing notes
as a dependency to useMemo() as we want a new object to be created when notes
changes. As setNotes
is coming from useState()
, it has a stable-identity, meaning that it's reference will remain the same through all renders of your app, so there is no need to pass that as a dependency (passing it won't hurt either though).