Home > Net >  UseContext with React Router
UseContext with React Router

Time:10-24

Shortly, when I try to use useState with useContext in one of my components, all pages just disappear. UseState in some reason block my Routers and I have no idea why... Can you tell me where is my mistake?

Some code below: Index.js

export default function App() {
  const [value, setValue] = useState(false)       -----> here I set the state
  return (
    <BrowserRouter>
      <UserContext.Provider value={{ value, setValue }}>
        <Routes>
          <Route path='/' element={<Layout />}>
            <Route index element={<Home />} />
            <Route path='Home' element={<Home />} />
            <Route path='Menu' element={<Menu />} />
            <Route path='Story' element={<Story />} />
            <Route path='Coffee' element={<Coffee />} />
            <Route path='Cart' element={<Cart />} />
          </Route>
        </Routes>
      </UserContext.Provider>
    </BrowserRouter>
  )
}

// ReactDOM.render(<App />, document.getElementById("root"))
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(<App />)

Buy.js component

import { useState } from "react"
import { useContext } from "react"
import { UserContext } from "../../UserContext"

const Buy = () => {
  const [buttonText, setButtonText] = useState("Add to cart")
  const [isActive, setIsActive] = useState(false)
  // const [value, setValue] = useContext(UserContext)   --> after I declare state everything disappears
  const addToCart = () => {
    setIsActive((current) => !current)
    // setValue(true)
    if (isActive) {
      setButtonText("Add to cart")
    }
  }
  return (
    <div>
      <button
        class='buy'
        style={{
          fontSize: isActive ? "0.8rem" : "1rem",
          color: isActive ? "lightgray" : "white",
        }}
        onClick={() => {
          addToCart()
        }}
      >
        {buttonText}
      </button>
    </div>
  )
}

export default Buy

UserContext.js

import { createContext } from "react"

export const UserContext = createContext(null)

Actually, I need this Context only for routes "Coffee" and "Cart", but if I wrap only this 2 routes will be the same problem and all is disappear. Should I maybe use Context in my Layout.jsx instead of Index.js? Thank you.

const Layout = () => {
  return (
    <>
      <Navbar />
      <Outlet />
      <Footer/>
    </>
  );
};

export default Layout;

The errors in console: errors in console

CodePudding user response:

Your context provides an object, not an array, so you should destructure using curly braces when you use it:

const { value, setValue } = useContext(UserContext);

Or if you want to keep this way of destructuring, you can return an array instead:

<UserContext.Provider value={[value, setValue]}>

CodePudding user response:

First i cannot see your Buy.js component between Context.Provider tree.

Then please try to use as object to destruct state values, not array.

CodePudding user response:

There are a few issues I see with the React code that I myself struggled with while learning React.

Issue #1

Your button in Buy.js has a class='buy' property. Rename that to className='buy' because that's just React's syntax.

Issue #2

Your button's onClick={} property should reference only the function's name, and should not call the function itself. Change the onClick to onClick={addToCart}. Do not add the anonymous arrow function, simply input the name of the function.

Possible Issue #3

Most of the conditional functionality you are looking for can be implemented with React's useEffect() hook. Change addToCart() in the following way:

const addToCart = () => {
setIsActive();
}

useEffect(() => {
  if(isActive) {
    setButtonText("Add to cart");
  }
}, [isActive]);

Make sure to import useEffect() before using this.

  • Related