Skip to content
Advertisement

pass data through the component tree without having to pass props down manually at every level

I have a sidebar on my site. The sidebar contains filters (date and time, model, category, etc.). Each filter is made in the form of a drop-down list.

I made the sidebar in such a way that the filters could save their state (selected value, open / closed) regardless of the screen size (that is, the selected values are not reset if the screen size changes).

But due to the fact that I have a lot of filters, my code in App.js is very cumbersome. Please tell me how to solve this problem without losing functionality.

App.js

export default function App() {
    const [hideSidebar, setHideSidebar] = useState(true);
    
    const [filterOneOpen, setFilterOneOpen] = useState(false);
    const [filterTwoOpen, setFilterTwoOpen] = useState(false);
    const [filterThreeOpen, setFilterThreeOpen] = useState(false);
    const [filterFourOpen, setFilterFourOpen] = useState(false);

    return (
        <ThemeProvider theme={theme}>
            <BrowserRouter>
                
                <AppContext.Provider value={{ filters, setFilters}}>
                    <div style={{display: 'flex', backgroundColor: '#f6f7f9'}}>
                    <button className="overlay-button-hidden"
                            style={{display: size.width > 600 ? "none" : "inline"}}
                            onClick={() => {setHideSidebar((prev) => !prev);}}>
            <ArrowBackIosNewIcon /></button>
          
          {size.width > 600 && (<FiltersSideBar
            filterOneOpen={filterOneOpen}
            setFilterOneOpen={setFilterOneOpen}
            filterTwoOpen={filterTwoOpen}
            setFilterTwoOpen={setFilterTwoOpen}
            filterThreeOpen={filterThreeOpen}
            setFilterThreeOpen={setFilterThreeOpen}
            filterFourOpen={filterFourOpen}
            setFilterFourOpen={setFilterFourOpen}/>)}

          <div style={{ display: "flex" }}>
            {size.width <= 600 && !hideSidebar && (<FiltersSideBar className="overlay"
                filterOneOpen={filterOneOpen}
                setFilterOneOpen={setFilterOneOpen}
                filterTwoOpen={filterTwoOpen}
                setFilterTwoOpen={setFilterTwoOpen}
                filterThreeOpen={filterThreeOpen}
                setFilterThreeOpen={setFilterThreeOpen}
                filterFourOpen={filterFourOpen}
                setFilterFourOpen={setFilterFourOpen}/>)}
            
            {size.width <= 600 && !hideSidebar && (
              <button className="overlay-button"
                      style={{display: size.width > 600 ? "none" : "inline"}}
                      onClick={() => {setHideSidebar((prev) => !prev);}}>
                
                <ArrowBackIosNewIcon /></button>)}</div>
                
                        <Routes>
                           <Route path="*" element={<Navigate to="/devices" replace />} />
                        </Routes>
                    </div>
                </AppContext.Provider>
             
            </BrowserRouter>
        </ThemeProvider>
    );
}

Advertisement

Answer

I made a wrapper component called FiltersContextWrapper, to hold the filters states and a context to control the state, this will clean the App.js component from the states and will keep the functionality as it is, please check.

https://codesandbox.io/s/ecstatic-worker-xt8fl5

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement