首页 > 解决方案 > 上下文有问题

问题描述

我了解上下文和在不进行道具钻探的情况下传递状态的能力(老实说,这似乎是相同数量的工作......我使用 redux 进行全局状态管理,除了样板之外,还可以使用 reducer、action creator 和redux 开发工具让我觉得它更有用)

即使使用 useContext 钩子,所需的代码量实际上与对我来说只是道具钻孔一样烦人......但也许我错过了一些东西

除了所有这些......我目前正在尝试拥有一个简单的导航栏功能,当打开汉堡菜单时,主页的背景会变成褪色的较暗不透明度。我不想要图书馆。我喜欢自己做这一切。

这是我的应用程序文件。我假设我可以将状态向下传递(打开),这将指示导航是否打开。但是,如果我唯一可以通过的是打开而不是 setOpen,我该如何更改打开状态...我不能在整个导航栏组件上设置 onClick 事件。我需要 onclick 甚至在导航中,但传递的只是状态本身。每次我认为我理解反应时,都会出现一些新的独特情况,我遇到类似的状态问题

// components
import Nav from './components/Nav'
import Homepage from './components/Homepage'
import React, {useState, createContext} from "react";

import {
  BrowserRouter as Router,
  Route,
} from "react-router-dom";

// pages
import About from './components/pages/About'
import Stories from './components/pages/Stories'
import News from './components/pages/News'
import ThemeContext from './ThemeContext';




// imports
function App() {
  const [open, setOpen]=useState(false)

  return (
    <>
<Router>

  <ThemeContext.Provider value={open}>
    <Nav />
  <Route path='/' exact>
    <Homepage />

  </Route>

  <Route path='/about' component={About} exact />
  <Route path='/stories' component={Stories} exact />
  <Route path='/news' component={News} exact />
  </ThemeContext.Provider>
</Router>
    </>
  );
}

export default App;

这是我的导航组件


import React, {useEffect, useState, useContext, useRef} from 'react'
import '../styles/custom.css'
import MenuDrop from './MenuDrop.js'
import {Link} from 'react-router-dom'
import ThemeContext from '../ThemeContext.js'

const Nav = () => {
  const [active, setActive]=useState(false)
  const [touched, setTouched]=useState(false)

  const myRef=useRef()

  const open=useContext(ThemeContext)

const clicker=()=>{
  if(window.innerWidth<450){
  setActive(!active);

}
}

useEffect(()=>{
  console.log(open)
},[active])



const toucher=()=>{
  setTouched(true);
}

const toucherOff=()=>{
  setTouched(false);
}

  return (
/*  NAVBAR */
<>
<div className={`shadow-xl ${open?'dark':'light'}`}>
    <div  className='nav c overflow-hidden w-full nav-main md:pt-8 pt-4  flex  justify-between md:justify-around items-center flex-row flex-shadow-2xl'>
        <h1 className=' mx-2   antialiased  text-lg md:text-3xl font-bold text-green-700 font-second-bold'>HUNTER SOLICITERS</h1>
        <div className={`${active?'nav-items-active':'nav-items'} bg-white items-center  md:items-center flex flex-col justify-center md:flex-row md:justify-around list-none w-1/3   flex-shadow-2xl`}>
        <Link onClick={()=>setActive(false)} to='/about' className='lg:mt-0 mt-20 text-green-800 hover:text-green-800 font-semibold duration-200 antialiased  p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>About</Link>
        <li onClick={()=>setActive(false)} className='text-green-800 hover:text-green-800 font-semibold duration-200 antialiased  p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>Contact</li>
        <Link onClick={()=>setActive(false)} to='/stories' className='lg:mt-0  text-green-800 hover:text-green-800 font-semibold duration-200 antialiased  p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>Stories</Link>
        <Link onClick={()=>setActive(false)} to='/news' className='lg:mt-0  text-green-800 hover:text-green-800 font-semibold duration-200 antialiased  p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>News</Link>
        <div onMouseLeave={()=>toucherOff()} onMouseEnter={()=>setTouched(true)} className='flex   flex-row items-center'>
        <li  onClick={()=>setActive(false)} className='text-green-800 hover:text-green-800 font-semibold duration-200 antialiased  p-2 cursor-pointer lg:my-0 my-6 text-sm lg:hover:text-white lg:hover:bg-red-900 font-main'>Team</li>
        <svg  className='hover:bg-red-900 text-black hover:text-white arrowTwo' xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
          </svg>
          </div>
    </div>

    <div onClick={()=>clicker()} ref={myRef} className={active?'mx-2 burger-active ':'burger mx-2'}>
    <div className={active?'toggle1 line-one':'line-one'}></div>
    <div className={active?' toggle2 line-two':'line-two'}></div>
    <div className={active?' toggle3 line-three':'line-three'}></div>
    </div>

    </div>
<MenuDrop toucher={toucher} setTouched={setTouched} toucherOff={toucherOff} touched={touched}/>
</div>
      </>
  )
}

export default Nav

这是我的主页组件

import React, {useContext, useEffect} from 'react'
// COMPONENTS
import Banner from './Banner'
import Footer from './Footer'
import GreenBanner from './GreenBanner'
import HomepageContentCards from './HomepageContentCards'
import HomepageContent from './HomepageContent'
import HomepageTeam from './HomepageTeam'
import WrappedMap from './Map'
import ThemeContext from '../ThemeContext'
import '../styles/custom.css'

// ASSETS
import imageTwo from '../images/home-image-two.jpg'
import imageThree from '../images/home-image-three.jpg'
import imageFour from '../images/home-image-four.jpg'

const Homepage = () => {
  useEffect(()=>{
    window.scrollTo(0, 0);
    console.log(open)
})

const open=useContext(ThemeContext)
  return (
<div className={`${open==='false'?'mt-0':'mt-20'} bg-container mt-10 md:mt-0 shadow-2xl`}>
    <Banner />
<div className='shadow-xl grid grid-cols-1 gap-0 lg:gap-0 lg:grid-cols-12'>
  <div class=" col-span-7">
    <HomepageContent />
        </div>
  <div class="">
    <HomepageTeam />
  </div>
    </div>
    <GreenBanner />
  <div className='grid grid-cols-1 gap-2 lg:gap-3 sm:grid-cols-3'>
    <HomepageContentCards image={imageTwo}/>
    <HomepageContentCards image={imageThree} />
    <HomepageContentCards image={imageFour} />
  </div>


  <div className='mt-8 lg:mt-0'>
    <WrappedMap
    isMarkerShown
    googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places$key=${process.env.REACT_APP_GOOGLE_KEY}`}
    loadingElement={<div style={{ height: `100%` }} />}
    containerElement={<div style={{ height: `400px` }} />}
    mapElement={<div style={{ height: `100%` }} />}
    />
  </div>

    <Footer />

    </div>
  )
}

export default Homepage

我正在使用顺风,所以忽略所有的类等。基本上我试图有一个简单的状态(导航栏是否打开并且汉堡是否已被按下打开它)....如果它打开了其余的背景东西(主页)通过使用条件渲染变为褪色不透明度的深色-->open?'dark':'light'

我可以向下传递状态,但是如果在上述父组件(App)中创建了状态和挂钩,我如何从挂钩向下传递函数(setOpen)或者如何从子组件更改状态

我发誓反应让状态管理有时对我来说很愚蠢

标签: reactjsreact-context

解决方案


推荐阅读