Issue of re-rendering the component on url change - reactjs

I'm new to react and I have some trouble re-rendering a component when I do my assignment.
On my navbar I have three links: Home, user and Courses.
If an user clicks on the "courses" (/courses?quick-courses=true#courses), the component will render and display the list of courses(the Links). If the user clicks on one of the Links such as "The Javascript"(/courses/3?title= Javascript) and then click the "Courses" (/courses?quick-courses=true#courses) from the navbar again, the content from the "courses" component will not be render again to display the list of course content.
I tried to use the shouldComponentUpdate() and componentDidUpdate() to assign the this.props.location.search to the state and many other ways to solve this issue. however it doesn't work for me.
Here's my components and what I did so far :components-assignment-3
Many thanks.

when you click /courses?quick-courses=true#courses you render this route <Route path="/courses" component={Courses} />
at this point, that route is loaded and mounted
then you click /courses/3?title= Javascript and you render <Route path={"/courses/:id"} exact component={Course} />
now clicking on /courses?quick-courses=true#courses won't re-render <Route path="/courses" component={Courses} /> again as it's already rendered, you're already inside of this route. that's why none of you lifecycle hooks will fire again and your showCourse will be false so that's why you won't see headerCheck

Related

Open component in new URL (React)

I have component with a button. I'd like a component to open another component in the new URL when the button is pressed. I don't want other components on the new page. I also want to pass data to a new component.
UPDATE:
<BrowserRouter>
<Link onClick={this.getData.bind(this)} to={{ pathname: "/test", data: this.state.data }}>Begin</Link>
<Switch>
<Route exact path="/test" component={Test} />
</Switch>
</BrowserRouter>
I wrote some code, but I have 2 problems:
How can I fetch data before route?
My component "Test" render on this page with previous components, I want only "Test" component on page
Please see react-router-dom for page to page navigation and passing data from one page to another.
You can use switch from react router dom along with routes. Please see documentation you will get to know about it.

React Rerender with radioButtons using redux

I have a question, I will appreciate if you could help me. I was building a simple react movie app, using redux for manage the state. I also use react router dom for manage basic routes.
I have the home page, where I render some radio buttons that when clicked they dispatch an action to filter the movies by a genre.
So my question is that when I clicked in a radio button it made the filter but the radio button it not checked.
Whereas if I put the Home component outside the Route it do it well, the radio button is checked and it filter the movies list.
This is the app component, with the home outside the router working well and the home inside the routing.
<Home props={props}/>
<Switch>
<Route exact path='/home' component={() => <Home props={props}/>} />
<Route path='/genre=:genre' component={detailGenre} />
<Redirect to='/home' />
</Switch>
This is the radio button
const handleRadioButtons = (e) => {
sortMovies(e.target.value)
}
...
<label htmlFor='horror'>Horror</label>
<input onChange={handleRadioButtons} name='filmtype' value='horror' type='radio' id='horror' />
I'm sure i'm not understanding some behaviour or maybe i'm missing something.
Thanks in advance.
Why is this happening and how can I solve it ?
The component prop tells React Router to generate the component using React.createElement, and if you pass it an inline function it will execute that function and generate the component anew with every single render. In other words, your Home component is being unmounted and remounted with every render. Try this instead, which is the standard way of rendering a component via a route with props:
<Route exact path='/home' render={() => (<Home props={props}/>)} />

navigating to new page does not cause previous page to be unmounted

I have a simple ionic app with an IonReactRouter
<IonApp>
<IonReactRouter>
<IonSplitPane contentId="main">
<Menu selectedPage={selectedPage} />
<IonRouterOutlet id="main">
<Route path="/new-user" component={NewUser} />
<Route path="/users" component={UserList} />
</IonRouterOutlet>
</IonSplitPane>
</IonReactRouter>
</IonApp>
When you navigate between new-user and users the corresponding pages (NewUser and UserList) are not unmounted:
According to this post this is by design
we need to control and keep pages around in the dom even if a user navigates away from them for page transition and state purposes
However I find that most end users expect clicking on 'New User' to show a fresh copy of the page. How can i make the page be unmounted OR achieve the same goal and 'reset' the page when a link is clicked?
You can use the Ionic Lifecycle events to reset the state of your form each time the user navigates to the new user page. IonViewWillEnter will fire each time the page is displayed, even though it is already mounted by React.
Check out the docs for usage information: https://ionicframework.com/docs/react/lifecycle
Try to add "key" to "IonRouterOutlet" component and update it on route changed.
An example for Vue:
<ion-router-outlet :key="route.fullPath" ></ion-router-outlet>

React component briefly renders the wrong data

I have a Profile component that checks to see if the user passed in url params. If not, the Profile component will render using the current logged in user. If they did, it will pull that value and use that userid for the Profile form.
Everything renders. And the proper profiles eventually appear, however if the user passes in different userid to view, the form will first render their own Profile...THEN render the passed in user.
I'm fairly confident that it's an issue of the props not being set at the time the first render occurs. My question is how can I prevent this?
I'm using react router 4.0. I setup a parent child component trying to do a conditional render...nothing seems to help.
My parent render function looks like this:
{this.props.match.params.userId && (
<ProfileForm
key={this.props.match.params.userId}
profileId={this.props.match.params.userId}
/>
)}
{!this.props.match.params.userId && <ProfileForm />}
My Route statement is this:
<Route exact={true} path={routes.PROFILE} component={Profile} />
<Route path={`${routes.PROFILE}/:userId`} component={Profile} />
Is there a way to prevent it from loading the "non-propped" version first or do I have to create a new component for "others" and have the route go there first?

How can I use react-router to trigger state changes?

I'm still coming to grips with React and react-router, but I'm wondering how to use react-router to simply update application state without re-rendering DOM nodes.
For example, suppose I have:
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute screen="main" />
<Route path="settings" screen="sync" />
<Route path="overview" screen="overview" />
</Route>
</Router>
I'd like to re-use react-router's matching but simply update the App component's current screen.
The reason is that suppose in the above example I have three screens arranged horizontally with only one visible at a time. When the route changes I want to animate in the appropriate screen. If I do that by assigning a component to each route, react-router doesn't render the other screens until the route matches, and there's a noticeable lag for the screen to slide in.
However, if I keep all three screens in the DOM and simply toggle state to trigger CSS transitions there is no lag (since, with appropriate use of will-change, the browser can pre-render the off-screen layer).
I've tried half a dozen ways of achieving this but they're all very hacky or involve duplicating the matching code somewhat. What am I doing wrong?
Also, I'd like to avoid adding something like Redux just to fix this if possible.
So you want something similar to Spectacle?
In your case I would place all the screens as children of the App component, and use react-router's params to know which screen you're on.
<Route path="/(:screen)" component={App}>
It will be avaialble as a prop to the App component:
class App extends React.Component {
componentWillMount () {
this.props.params.screen
}
}
More about route params at react-router/injected-props
If you're having trouble with re-rendering you can use the component lifecycle method shouldComponentUpdate. Returning false in this method will prevent the component from re-rendering and you'll have the new props (which also include the route params).
class App extends React.Component {
shouldComponentUpdate (nextProps) {
nextProps.params.screen
return false
}
}

Resources