Render another root path with own routes - reactjs

I am trying to figure render a complete seperate admin path with its own routes.
Is it possible to render say admin page that is with and existing project.
At the moment I have the following code it is working very well.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './client/App.js';
import Admin from './admin/admin.js';
var pathname = window.location.pathname;
if (pathname.substring(0, 6) == '/admin') {
ReactDOM.render(<Admin />, document.getElementById('root'));
} else {
ReactDOM.render(<App />, document.getElementById('root'));
}

I'm struggling to understand what you want to do exactly. You already have everything you need, Admin and App are components and therefore small projects I would say. However, you shouldn't do it that way and instead use react-router it avoids you to check the window location pathname by yourself and will save you a lof of time and headache.

Related

Let only one page be server-side rendered with Meteor

My Meteor/React application should render one static page besides the reactive one pagers with reactive UIs. The static package does not even need to be "hydrated" with the React magic after displayed in the browser. Though the server-side rendering on the server will be dynamic with React components.
I got it working, but I'm not sure if it is the intended official way to do it.
File import/client/routes.js
...
<Route path="/reactive/pages/:id" component={ReactiveComponent} />
<Route path="/static_url" />
...
File server/main.jsx
...
onPageLoad((sink) => {
if (sink.request.path === '/static_url) {
sink.renderIntoElementById('app', renderToString(
<StaticPage />,
));
}
});
...
File client/main.js
...
import { Routes } from '../imports/client/routes';
Meteor.startup(() => {
...
if (window.location.pathname !== '/offer_pdf') {
render(Routes, document.getElementById('app'));
}
});
...
Especially when rendering dependent on the URI, it seems a little bit hacky to me. Does a more elegant solution exist?
I don't think there is anything official, but in general, of course, it's a good idea to use a router for rendering different pages, so I thought it worth pointing out that you can use react-router on the server as well:
import React from "react";
import { renderToString } from "react-dom/server";
import { onPageLoad } from "meteor/server-render";
import { StaticRouter } from 'react-router-dom';
import App from '/imports/ui/app.jsx';
onPageLoad(sink => {
const context = {};
sink.renderIntoElementById("app", renderToString(
<StaticRouter location={sink.request.url} context={context}>
<App />
</StaticRouter>
));
/* Context is written by the routes in the app. The NotFound route, used
when, uhm, no route is found, sets the status code. Here we set it on the
HTTP response to get a hard 404, not just a soft 404. Important for Google bot.
*/
context.statusCode && sink.setStatusCode(context.statusCode);
// add title to head of document if set by route
sink.appendToHead(`<title>${context.title || 'My page'}</title>`);
});
In App you can then use the usual Switch and Route tags for specifying different routes. In that you could, for instance, only specify routes that you want to be server-rendered.

Navigating Using React Router From a Button Outside the React App

I have a simple demo react app that uses react-router-dom (5.2) to show one of 3 "pages".
The app is included on a page that has a button:
index.html:
<button data-app-button data-sku='woo-beanie'>Click Me</button>
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
document.addEventListener('click', function (event) {
if (event.target.closest('button[data-app-button]')) {
// send instructions to react
}
});
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
I want to be able to navigate to a page in the react site, passing through the buttons data-attributes. How is this done with react and react-router ?
UPDATE
#Doppoio's solution works - as long as I'm on a different "page" in my react app. However I have a route like this:
<Route
path="/tryon/:id/:product_sku?">
</Route>
If I start in app from a route of say /faqs and my external button navigates to /tryon/242/jumper-23 my component is awar of the product_sku property.
However when I'm on a page in app of /tryon/242 and then i click an external button to navigate to /tryon/242/jumper-23 the component should be aware of the jumper-23 optional parameter. Currently it isn't.
How do i make the Tryon component detect the change in url of just the optional parameter?
Somewhere in your code under Router, you can add history to window object. And call it from there.
const SomeComponentInsideRouter = () => {
const history = useHistory();
useEffect(() => {
window.reactHistory = history; // Add reference to history via window object.
}, []);
return null;
};
And call it via window.reactHistory
document.addEventListener("click", function (event) {
if (event.target.closest("button[data-app-button]")) {
// send instructions to react
window.reactHistory.push("/about");
}
});
Here's sandbox link
https://codesandbox.io/s/happy-ganguly-b0u2o?file=/src/index.js
Update to mention changed props:
Changes to the props can be detected using componentDidUpdate
https://reactjs.org/docs/react-component.html#componentdidupdate

How to restrict reactjs from cacheing API data

I am new to reactjs. In my project front end is react and backend in slim.There I noticed a issue that whenever I make changes in API then its not reflected on front end until and unless I dont clear my browser cache.Its also happening for production project.
Is I am missing anything here in reactjs? Why it cacheing the API data
A solution that may work is to comment out registerServiceWorker and import unregister and invoke it.
import App from './App';
// import registerServiceWorker from './registerServiceWorker';
import { unregister } from './registerServiceWorker';
unregister();
ReactDOM.render(
<App />,
document.getElementById('root'),
);
Refer here for other suggestions! (https://github.com/facebook/create-react-app/issues/1910)

import App from './App';

I am trying react based on create-react-app. I'm new to react.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
./App in import App from './App'; is not clear to me when and where is this created, is this done by babel?
file strucutre
my-app/
README.md
node_modules/
package.json
.gitignore
public/
favicon.ico
index.html
src/
App.css
App.js
App.test.js
index.css
index.js
logo.svg
App.js
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>myComponent</div>
)
}
}
export default App;
tl;dr
No, it is not done by Babel, instead it is done by create-react-app package.
All the files and folders in that folder are created automatically when you run,
create-react-app your-new-app-name
import App from './App'
The above line is used for importing the class you have written in the file App.js under the same directory.
Next, the difference between,
import App from './App'
and
import App from 'App'
Use the first if you want to import any user defined files and second for importing packages. As Shubham Khatri mentioned, for importing files, it is technically same if you did or did not use .js extension.
The longer version
create-react-app is a starter kit for people who are new to React or for who are lazy enough to build an app from scratch. What create-react-app does is, it will give you a minimal running React app with a solid folder structure. As given in their documentation, you can install that globally by giving,
npm install -g create-react-app
After this whenever you want to create a new app, what you want to do is,
create-react-app your-new-app-name
This will automatically generate a folder with all the files you mentioned.
Within the folder when you open the file public/index.html, you can see a line
<div id="root"> </div>
And on the src/index.js, you can find,
ReactDOM.render(
<App />,{}
document.getElementById('root')
);
If you are familiar with javascript, you may know that document.getElementById('root') is used to match any tag in HTML with ID as root. So the above snippet means that, they are rendering the <App> component of react to div with ID root. This is how React communicates with HTML page.
Rather that writing all the component codes in a single file, it is a good standard to write each components in different files. Here, App.js is a component that basically renders the text myComponent. For using this component in other files, you have to do two things.
Export the component from the file where it is defined. (export default App;)
Import the component to the file where it is used. (import App from './App')
General syntax for import is,
import className, { functionName } from 'packageName'
or
import className, { functionName } from './path-to-file/fileName'
Note: It is that ./ which tells the compiler whether to look on to node_modules folder or the path you mentioned. Use that strictly when you need to import user defined files.
Hope this helps!
When you import your Component like
import App from './App';
It will import your file App.js that is present in the same direcotry as index.js
In webpack configuration we specify which types of files babel needs to build and there if we specify .js or .jsx, it takes by default the extension of the file when we import it. we do not explicitly mention it. You can change your immport to be like
import App from './App.js';
which is technically the same.
The create-react-app npm package makes use of webpack to build your code which you can see from the package/react-scripts/package.json in the github directory

React-router with createBrowserHistory for partial and full page reloads

I am trying to use react-router v1.0.0 for full page and partial reloadable urls.
I have the following "History.jsx" file,
import BrowserHistory from 'history/lib/createBrowserHistory';
export default new BrowserHistory();
and I import it in my main entry file "app.jsx" like following,
import React from 'react';
import ReactDOM from 'react-dom';
import Router from 'react-router';
import Routes from './../utils/Routes.jsx';
import history from './../utils/History.jsx';
ReactDOM.render(
(<Router history={history}>{Routes}</Router>),
document.getElementById('pageSpecific')
);
Now when i navigate to "localhost:8080", it shows the page good. When i click on a href in the page, it takes to "localhost:8080/example" correctly without the "#" in the URL and it does not reload the page. Its all good.
Now that my URL is "localhost:8080/example" and when i try to refresh the page, it says "cannot get /example". This is problem which i am not able to solve!
Am i doing anything wrong? I am really struck in this place!!

Resources