Re-routing a Component without Reloading Entire Page - reactjs

I have a React+Django app which is a custom video player, and I'm currently working on a related videos / queue at the end of the video. I have it working, if I use a simple window.location.replace with the link to the next video. However, it would be a lot smoother to only reload the video player.
From the many many threads I've read on SO, it seems that this it is possible to re-route my "main" component within a child component in React, but none of the methods have worked for me and I have a slightly different case than everything I've read. If the video playing depends on my URL (or Route), is it even still possible to reload without re-rendering the entire page?
Here's a barebones version of the relevant code:
Index.js:
class Welcome extends React.Component {
render() {
return (
<BrowserRouter>
<App/>
</BrowserRouter>
)
}
}
const element = <Welcome/>;
ReactDOM.render(
element,
document.getElementById('container')
);
App.js:
class App extends React.Component {
render() {
return (
<Row id="app-container" className="h-100 justify-content-center align-items-center">
<Switch>
<Route path='/app/:number' component={Player}/>
</Switch>
</Row>
)
}
}
export default App
Queue.js, Note: this is obviously just the part I'm having trouble with. I have clickable imgs to do the window.location.replace method.
<div>
<Link to='app/1' replace>
Previous Video
</Link>
<div>
The Link actually does change the URL in the way I want, but doesn't reload the App. I've spent a long time trying to implement solutions to this problem from other SO posts, but I'm worried that once I get it, it will end up forcing the whole page to reload anyway. Can anyone tell me if it's possible to JUST re-reroute my app? It's alright if the URL doesn't change, as long as the app is based on the new route.
Thanks in advance

Related

Rendering 2 navbar

noob question but I wanted to ask if I am creating a react app that has a front-end and back-end interface. How would I add a navbar for each of them. I am thinking of creating a private route for the backend interface and then adding my navbar there, But navbar on App.JS would clash with that. Am I right to think that, if so how can I fix it?
Here is an example:
function Users() {
let location = useLocation();
return (
<div>
<div>
{location.pathname === "/backend-navbar"?
<p>back-end navbar</p> : <p>front-end navar</p>}
</div>
</div>
);
}

Prevent remounting of expensive (class) component with shouldComponentUpdate() (List of images, inside router)

I'm rendering a very large list of images that, when clicked individually, are added to a "viewer" div. The problem is that each time I add an image to the viewer, the original list re-renders, even though no changes have been made to the list's content.
I've tried using shouldComponentUpdate() at every level, as well as using React.memo. Neither appear to have any effect. I've also looked in to whether the time should be spent making the components functional and researching hooks (useContext() looks enticing), but I'm too new at React to know if that would just be more time wasted. (Please feel free weigh in on whether this is a waste of time.)
I don't know where the problem is, so I'm not sure a snippet would do much good. Instead, I've stripped down the problem to its bones and posted a sandbox version here
https://codesandbox.io/s/async-darkness-l920b
At the moment, my shouldComponentUpdate comparison is pretty straightforward for each class; something like:
if (nextProps.photoData === this.props.photoData) {
return false;
} else {
return true;
}
If you open the codesandbox console you'll see I'm logging Year.js > <ImageList /> is rendering to flag each successive render of the list in question.
Any help, even a nudge in the right direction, would be hugely appreciated. I've been reading blog articles for a solid day now and nothing seems to help.
That's because the PhotoView in App.js is defined inside render method, so when state update causing the render, then the PhotoView redefined again. It's a new component every time for The App component.
Please define components outside the render function:
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Year from "./Year";
import Viewer from "./Viewer";
import dataObj from "./dataObj.json";
import "./App.css";
class App extends React.Component {
constructor(props) {
super(props);
this.PhotoView = this.PhotoView.bind(this)
this.state = {
current: {
year: 2019,
url: ""
},
viewerData: [],
photoData: null
};
}
componentDidMount() {
this.setState({
photoData: dataObj
});
}
addToViewer = moment =>
this.setState(state => {
const viewerData = state.viewerData.concat(moment.props.data);
return {
viewerData,
value: ""
};
});
About() {
return (
<div>
<h1>About</h1>
</div>
);
};
PhotoView(url) {
return (
<div className="PhotoView">
<Year
setCurrent={this.setCurrent}
photoData={this.state.photoData}
addToViewer={this.addToViewer}
/>
<Viewer
viewerData={this.state.viewerData}
setCurrent={this.setCurrent}
/>
</div>
);
}
render() {
return (
<div className="App">
<Router>
<nav>
<Link to="/about">About</Link>
<Link to="/">Photo View</Link>
</nav>
<Switch>
<Route path="/about" exact component={this.About} />
<Route path="/" component={this.PhotoView} />
</Switch>
</Router>
</div>
);
}
}
export default App;
Or move them to individual files.

Should you wrap your whole app with a React Context Provider?

I want to save a simple boolean + userID if a user is authenticated and have it accessible via React Context API.
Many guides wrapped their root compoennt with the context Provider. To me it seems wastefull to wrap the whole app. On the other hand I need this information to be available in all my main pages.
Does it have any negative consequenses to wrap your whole app with a React Context Provider?
Example:
class App extends Component {
render() {
return (
<MyProvider>
<div className="App">
<h1 className="App-title">Welcome to my web store</h1>
<ProductList />
</div>
</MyProvider>
);
}
}
I used this guide as a reference.
I do not have any experiences in React Redux so this might just natural to everyone who has used this framework before.
Researching Google brings up many guides on how to implement React Context or use HOC but the 15 I clicked did not answer my question.
#Fyodor pointed it out in his comment:
You can wrap whole app in provider. React-redux recommends the same
(react-redux.js.org/introduction/…), so you may consider it acceptable
practice

Swipe through components with big data sets (React)

I'm building a React app that takes in a lot of data from temperature sensors at several different places and displays the data with chart.js.
I have made one component that fetch data from one place and that component is called from App.js, so now I could copy this component / or fetch data from another place if I implement it that way.
Next step is to find a way to swipe through these components. I don't know what to use or how I would go about to solve this, so I'm looking for ideas on how to solve this.
I have tried using react-swipeable-views. Code is provided in this post. This seems to be a simple solution, but I'm not sure if it's a good idea to do like this. I guess it would be quite heavy with large data sets? If I understand the way React works it would pull in data from all components to a browser and then hide it until it's showed?
I have also looked at this article: https://coursework.vschool.io/react-transitions-with-react-transition-group/
Here react-transition-group is used, but I'm not sure on how to implement the swipe part here since that is not discussed in the article.
Any ideas on how to solve this?
import React, {Component} from 'react';
import Test from './Test';
import SwipeableViews from 'react-swipeable-views';
const styles = {
slide: {
padding: 15,
minHeight: 800,
color: '#fff',
},
slide1: {
background: '#FEA900',
},
slide2: {
background: '#B3DC4A',
},
slide3: {
background: '#6AC0FF',
},
};
class App extends React.Component{
constructor(){
super();
this.state={
foo: 'bar'
}
}
}
render(){
return(
<div className="App">
<SwipeableViews enableMouseEvents>
<div style={Object.assign({}, styles.slide, styles.slide1)}>
slide n°1
<Test /> // <-- This would be a component with large data sets
</div>
<div style={Object.assign({}, styles.slide, styles.slide2)}>
slide n°2
</div>
<div style={Object.assign({}, styles.slide, styles.slide3)}>
slide n°3
</div>
</SwipeableViews>
</div>
)
}
export default App;
I have not used it before but looking at the docs, using react-swipeable-views should be fine, since it "quickly renders the first slide, then lazy-loads the others." (from https://github.com/oliviertassinari/react-swipeable-views). Furthermore you can customize how many slides before and after the currently displayed one are being rendered (see https://react-swipeable-views.com/api/api/#virtualize).
Also, it might be a good idea, to catch up on some react concepts (https://reactjs.org/docs/introducing-jsx.html). React does not "hide" any components, it only renders the ones you choose to the DOM and updates what is necessary to get the DOM to reflect your state. So for example, if you have multiple pages (p1, p2, p3), each rendering one component (c1, c2, c3), while being on page p1, only the component c1 would be rendered to the DOM.

How do I modify a page title based on react component using .NET Core react with redux project?

I thought this would be simple, and the answer probably is and I'm just missing something, but I'm having trouble with updating a header/layout component based on what page I'm on.
Code wise, I have just installed the ASP.NET Core 2.0 template that uses React with Redux. I'm familiar with React, but TypeScript and Redux is new to me so it's hopefully a syntax/layout issue I'm having, as I can do this in a standalone React project. If you create a new project in Visual Studio following this template, you'll see the code that I'm trying to modify (New > Project > ASP.NET Core Web Application > React.js and Redux).
The TypeScript Layout file (ClientApp/components/Layout.tsx) is where I want to put essentially:
<h1>{ this.state.title }</h1>
...and further on from this use a Header tag to load a Header component that holds the title.
I want to then change the title based on whether I am on the Home, FetchData, or Counter page, which I imagine is just a basic string set on each component file.
If you can't open the project file for whatever reason, here is the layout I'm working with:
Layout component (should set the title here)
import * as React from 'react';
import { NavMenu } from './NavMenu';
export interface HeaderState {
title: string;
}
export class Layout extends React.Component<{}, {}> {
public render() {
return <div className='container-fluid'>
// !!!!---> Create a <Header /> component that includes the page title, set on a page by page basis
<div className='row'>
<div className='col-sm-3'>
<NavMenu />
</div>
<div className='col-sm-9'>
{ this.props.children }
</div>
</div>
</div>;
}
}
I would potentially include more component code for those who can't use the Visual Studio project, but it's pretty bloated with a lot of code that doesn't apply here. I just thought someone could help without needing it, but happy to provide if necessary!
Any help or pointers in the right direction are greatly appreciated! Apologies if this question and answer is somewhere. I have Googled and searched SO but no luck.

Resources