I am working on project that will use Reactjs on top off rails application.
So i set up my project following this link
Set up Rails with React and Es6
Everything is working fine but i change my bundle.js to this
require('./main');
Then inside main.js i have this
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route } from 'react-router';
import { browserHistory } from 'react-router';
/*Import Component*/
import NotFound from './components/NotFound';
/*
*
* Routes
*
* */
var routes = (
<Router history={browserHistory}>
<Route path="/" component={NotFound}/>
</Router>
);
ReactDOM.render(routes , document.querySelector('#main'));
So inside my component file (/components/NotFound.js)
I have this
import React from 'react';
var NotFound = React.createClass({
render : function () {
return (
<div>
<h1>Not found</h1>
</div>
)
}
});
export default NotFound;
It can be displayed smoothly but the problem is
when i change some code inside my component file (in this case /components/NotFound.js) then refresh the page.
It took around 3 Seconds for just 1 line of code that i added to my component file.
So this is so painful because it took a huge amount of time just for edit a few line of code.
So anyone know how can i reduce the build time to be less than this?
Thanks a lot!
Related
This question already has answers here:
Why useEffect running twice and how to handle it well in React?
(2 answers)
React Hooks render twice
(5 answers)
Closed 5 months ago.
Why is this duplicating in the console? I noticed this while working on another projects and noticed the amount of HTML elements I was adding using jQuery was twice as much as expected (building a notification framework). I tried recreating the problem in a new project and the behavior persisted
DupeMountTest.js:
import React, {Component, useEffect} from "react";
const DupeMountTest = () => {
useEffect(() => {
console.log("useEffect")
}, [])
return (
<div>
<p>Test</p>
</div>
)
}
export default DupeMountTest
App.js:
import {
BrowserRouter as Router,
Route, Routes,
} from "react-router-dom";
import DupeMountTest from "./DupeMountTest";
function App() {
return (
<Router>
<div className="App">
<Routes>
<Route path={"/"} exact element={<DupeMountTest/>}/>
</Routes>
</div>
</Router>
);
}
export default App
index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Console:
I also attempted this using a class component but "Mounted" also logged twice.
DupeMountTest using class component:
import React, {Component, useEffect} from "react";
class DupeMountTest extends Component {
componentDidMount() {
console.log("Mounted")
}
render() {
return (
<div>
<p>Test</p>
</div>
)
}
}
export default DupeMountTest
Answer provided by evolutionxbox inside the comments section. Problem solved by removing <React.StrictMode> in index.js:
Updated index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// <React.StrictMode>
//
// </React.StrictMode>
<App />
);
React 18 introduces a new development-only check to Strict Mode. This
new check will automatically unmount and remount every component,
whenever a component mounts for the first time, restoring the previous
state on the second mount.
https://reactjs.org/blog/2022/03/29/react-v18.html#new-strict-mode-behaviors
So, your useEffect is running twice on each mount.
This was put in place to lay the groundwork for future features, so it's not exactly a bad thing.
In the future, we’d like to add a feature that allows React to add and
remove sections of the UI while preserving state. For example, when a
user tabs away from a screen and back, React should be able to
immediately show the previous screen. To do this, React would unmount
and remount trees using the same component state as before.
This feature will give React apps better performance out-of-the-box,
but requires components to be resilient to effects being mounted and
destroyed multiple times. Most effects will work without any changes,
but some effects assume they are only mounted or destroyed once.
It's also discussed in this post (thanks #evolutionxbox):
React Hooks render twice
I really liked a comment there that basically summed up the answer to what you're wondering about:
"it's a feature, not a bug."
I have observed that suddenly CSS path in my project is changed, I am not sure about the reason whether this is a configuration issue or any other, but because of the path CSS is taking too much time to load.
I have already tried to check imports and everything in the code but it seems proper
Please check the below image for path comparison between the new and the backup folder.
New Path:
Old Path
Note: I need the path to be like old where react convert the css to inline, this runs faster.
Below is how I have imported my custom CSS in index.js:
import * as serviceWorker from './serviceWorker';
import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import { render } from 'react-dom';
import App from './App';
import './index.css';
import './utilities/animate.css';
//react and redux related library
import { Provider } from 'react-redux';
import store from './redux/store/index';
class Main extends Component {
render() {
return (
<Route path='/' component={App} />
);
}
}
let rootElement = document.getElementById('app');
render(<Provider store={store}>
<BrowserRouter >
<Main />
</BrowserRouter>
</Provider>, rootElement);
serviceWorker.unregister();
I have run npm update and updated few packages, may be some of the packages were corrupted or outdated. This fixed my issue of performance and CSS loading slow.
I've implemented an App component which contains a Route using React and React router:
import {
BrowserRouter as Router,
Route
} from 'react-router-dom';
import createHeader from './components/header/header';
import createLandingPage from './components/landing-page/landing-page';
import createFooter from './components/footer/footer';
export default React => () => {
const Header = createHeader(React);
const LandingPage = createLandingPage(React);
const Footer = createFooter(React);
return (
<section id="sectionId">
<Header />
<Router>
<Route exact path="/" component={LandingPage} />
</Router>
<Footer />
</section>
);
};
The app itself renders and works properly, as I can go to my browser and see everything as expected.
The problem arises when I try to implement proper testing, which runs in Node.js without a browser:
import test from 'tape';
import dom from 'cheerio';
import React from 'react';
import reactDom from 'react-dom/server';
import { MemoryRouter } from 'react-router';
import createApp from './app';
const render = reactDom.renderToStaticMarkup;
test('App init & render', assert => {
const message = 'It sohuld initialize and render the app.';
const App = createApp(React);
const $ = dom.load(render(
<MemoryRouter>
<App />
</MemoryRouter>
));
const output = $('#jptv').length;
const actual = output > 0;
const expected = true;
assert.equal(actual, expected, message);
assert.end();
});
I used MemoryRouter to wrap my app as indicated in React docs to avoid errors, but with or without it, I have the same error when running the test in the console:
Invariant Violation: Browser history needs a DOM
My guess is that I cannot run a component using BrowserRouter out of the browser, yet I don't understand what would be the proper way to test it, as I don't want to force myself to manipulate the code as to fit the test environment shortcomings.
I've searched the web and look into similar issues, but I cannot find an answer, and the docs offer little if no useful information to deal with this.
Any help will be most appreciated.
Thanks!
Tried to upgrade react-router from 2 to 4 and broke it and now cant render my app.
getting various errors (the most recent is: <Route> elements are for router configuration only and should not be rendered)
I have also had the error where my ./ route renders fine but every other route blows up when I refresh and says Cannot GET /randomRoute
I am creating a react app and my main index.js file (where I include ReactDOM.render) also includes the routes and looks like so:
import React from 'react';
import ReactDOM from 'react-dom';
import { Route } from 'react-router';
import { BrowserRouter as Router, Match, HashRouter } from 'react-router-dom'
import Header from './components/header';
import './index.scss';
class App extends React.Component {
render() {
return (
<Router history={HashRouter}>
<div>
<Route path={"/"} component={Header} />
</div>
</Router>
);
}
}
ReactDOM.render(<App />,
document.getElementById('content'));
why would I be getting that current error and can anyone give me a simple start to the basics I need to include just to get routing working? it worked in version 2 but I wanted to upgrade and now cant get it working again
The problem is that you are specifying history object as a Router type.
From the Documentation
A <Router> that uses the hash portion of the URL (i.e.
window.location.hash) to keep your UI in sync with the URL.
This is similar to what you would do when you specify history as
hashHistory in Router v2.
Also, history object has been seprated into a seprate package from v4 onwards.
You can either make use of BrowserRouter or HashRouter to render your Routes.
Change your Route Configuration to below if you want to use BrowserRouter which is <Router> that uses the HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URL.This is similar to what you would do when you specify history as browserHistory in Router v2.
Also you need to import Route from 'react-router-dom'.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Match, Route} from 'react-router-dom'
import Header from './components/header';
import './index.scss';
class App extends React.Component {
render() {
return (
<Router >
<div>
<Route path={"/"} component={Header} />
</div>
</Router>
);
}
}
Well, in react router v4 the API is different. You have to define it in your index.js file like this,
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<Switch>
<Route path="/path/one" component={ComponentOne} />
<Route path="/path/two" component={ComponentTwo} />
<Route path="/" component={IndexComponent} />
</Switch>
</div>
</BrowserRouter>
</Provider>
, document.querySelector('.container'));
Make sure the order is important here. Put the most generic one at last. Hope this helps. Happy coding !
I am currently to adapt a simple web app i made (using React and Redux) into a native desktop app.
I am using GitHub's Electron and Webpack to do this. Everything is fine if I use hashHistory from React-Router.. but I want to use browserHistory so my app will still look nice (URL-wise) when running as a webapp. If i do this though, I get the following error:
No route matches path ".../index.html"
Which makes sense to me. I am loading index.html as the main file for Electron:
mainWindow.loadURL('file://' + __dirname + '/index.html');
I'm just wondering if it is at all possible to use browserHistory with React-Router and Electron. If anyone knows it would be greatly appreciated!
Not exactly. But there is even better solution .
You should Separate from your react app the bootstrap file.
Bootstrap file which load your app and pass to it some additional params from outside.
In your situation you will create two bootstrap files, one for electron - with memoryHistory (I think it is better for electron) and second one for browsers with browser history.
Example of bootstrap file for electron index-electron.jsx:
import React from "react";
import ReactDOM from "react-dom";
import { createMemoryHistory } from "react-router";
import App from "./App.jsx";
const initialState = window.__INITIAL_STATE__;
const config = window.__CONFIG__;
const history = createMemoryHistory("begin-path");
ReactDOM.render(
<App
config={config}
history={history}
initialState={initialState}
/>, document.getElementById("root"));
Example of bootstrap file for browsers index-browser.jsx:
import React from "react";
import ReactDOM from "react-dom";
import { browserHistory } from 'react-router';
import App from "./App.jsx";
const initialState = window.__INITIAL_STATE__;
const config = window.__CONFIG__;
ReactDOM.render(
<App
config={config}
history={history}
initialState={initialState}
/>, document.getElementById("root"));
In my examples difference is small (only history) but you can make more changes. As you see I also provide additional begin params from outside (initialState, config);
And how your App should :
import React from 'react';
import { Router, Route } from 'react-router';
class App extends React.Component {
static propsTypes = {
history: React.PropTypes.object,
config: React.PropTypes.object,
initialState: React.PropTypes.object
};
render() {
return (
<Router history={this.props.history}>
<Route ...>
...
</Route>
</Router>
);
}
}
export default App;
Above code is only conception. It is from my project, where I removed obsolete things. Therefore without some modification it may not work
Now for electron you use index-electron.jsx, and for browsers index-browser.jsx. Most of your code is reusable cross both envs. And it is very flexible.