Context API bringing state up to higher component

61 Views Asked by At

I'm trying to get my nav bar to change depending on which page the app is on without having to create individual nav components for each page. I want the nav bar to change once the user goes to a new 'projects' page. The way I would do this is to conditionally render the nav bar elements depending on the url parameter. Once the user clicks to go to the project page, there will be a url parameter such as localhost/project/movie. However, the nav bar component does not have access to the match.params.projectId, only the project page component has access to it since it's within a Route component from react-router. Therefore, I want to make a global state that stores the url parameter so that I could use it within the navbar component to conditionally render the elements of that component.

Highest level App component

const App = () => {
  return (
    <div className="app">
      <Header/>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route exact path="/project/:projectId" component={ProjectOverview}/>
      </Switch>
    </div>
  );
}

Lower level Project page component

const ProjectOverview = ({ match }) => {
    useEffect(() => {
        window.scrollTo(0, 650);
    }, []);

    let project = {};

    if(match.params.projectId === 'movie'){
        project = {
            p: 'Browse your favorite Movies, TV shows, and actors. Search for specific movies, shows or actors by date, rating, region and other categories. Browse the latest and greatest films and to find information about its actors, crew, and reviews. Rate and favorite Movies, TV shows and actors while having access to them through a user account. Login / Authentication.',
            img: 'http://www.technologies.com/images/cloud-summary.png',
            gif: 'https://giphy.com/media/mUgG6FZuWN9V1/giphy.gif',
            list: ['React', 'Redux', 'Hooks', 'TMDB API', 'Sass', 'React Router']
        }
    } else if(match.params.projectId === 'ecommerce'){
        project = {
            p: 'Something else',
            img: 'http://www.technologies.com/images/cloud-summary.png',
            gif: 'https://giphy.com/media/IgASZuWN9V1/giphy.gif',
            list: ['React', 'Redux', 'Hooks', 'TMDB API', 'Sass', 'React Router']
        }
    }

    return(

I know the provider has to wrap around the header(navbar) component within the app component but the state value that is needed (match.params.projectId) can only be found within the project page component. I'm wondering how I could get the value for the provider to be whatever the url parameter is within the project page component. I will try to further clarify my question if it seems too confusing for anyone. Thank you

1

There are 1 best solutions below

1
On BEST ANSWER

I don't know if it is the best solution, but in an application where I had to change the nav's title depending on the route I did the following:

function App() {

  const [title, setTitle] = useState('');

  return <Router>
      <Navbar title={title} />
       <Switch>
         <Route path="/product/:id" exact render={props => <ProductPage {...props}  setTitle={setTitle} />} />
       </Switch>
       </Router>
}

And in the ProductComponent:

function ProductionComponet({setTitle, match}){
 useEffect(()=>{
   setTitle(`product ${match.params.id}!`)
 },[])
}