react router redux initial state setting on isomorphic app - javascript

I am writing an isomorphic app with react, redux, react-router, react-router-redux.
I am calling syncHistoryWithStore on client.js. But on initial load, router.locationBeforeTransitions is always null. It is populated once I navigate though.
const history = syncHistoryWithStore(browserHistory, store);
...
<Router routes={routes} history={history} />
Above code is from client.js
Should I fire LOCATION_CHANGE action on server side manually to populate initial state of react-router-redux?

You will be creating a new store on client hence the state from the store created on server is lost. We will need to pass the initial state from server to the client, so it can populate its store.
on Server:
const initialState = store.getState();
now add this to your HTML template rendered from server:
<script type="application/javascript">
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
</script>
on Client:
let initialState = window.__INITIAL_STATE__;
use the initialState when you createStore on Client.

Related

Unable to use router.push in Reactjs

I am working on Reactjs and using nextjs,Right now i am trying to refresh page (using routes) but i am getting following error
Error: No router instance found. you should only use "next/router" inside the client side of your app.
Here is my current code
const Post = ({ post, blogs }) => {
const routers = useRouter();
var spath=routers.asPath;
routers.push({ pathname: spath, query: '' });
})
You probably used router outside of a functional component or hook.
Convert Post to hook and it should work.
If you are running this code on application load or on any data change. You should do this inside useEffect hook because while rendering application on sever router won't be there and useEffect runs only inside browser.

React Hot Reload with Redux-Saga

I'm using React Hot Reloader on my project and recently noticed a strange behavior of the redux store in pairs with Hot Reloader.
When I load the page for the first time, my page component calls an action to retrieve a particular data (this is doing in useEffect hook), everything works fine - action triggers once and calls backend properly:
When I make a change in the code and save it, Hot Reloader reloads my component and dispatch action twice (as a result - 2 calls in the network tab):
Same story with further code changes:
I wrap my main app component and redux store with hot reload middleware:
index.js
// Create a reusable render method that we can call more than once
const render = () => {
// Dynamically import our main App component, and render it
const MainApp = require('./MainApp').default;
ReactDOM.render(
<MainApp />,
rootEl,
);
};
if (module.hot) {
module.hot.accept('./MainApp', () => {
const MainApp = require('./MainApp').default;
render(
<MainApp />,
rootEl,
);
});
}
render();
store.js
const store = createStore(reducers(history), initialState,
composeEnhancers(applyMiddleware(...middlewares)));
sagaMiddleware.run(rootSaga);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers/index', () => {
const nextRootReducer = require('../reducers/index');
store.replaceReducer(nextRootReducer);
});
}
Are there any ways to fix that? Why it is happening?

In a react components, how to get latest data from state once it is changed from another component using redux?

There are three components in my code.
cart.js
datepicker.js
usertotal.js
And an action to get the data from the database
action.js
And a reducer function handling actions from actions.js
Each component has been receiving data through action {dispatch}.
I need to change the data using action (if the component’s state is changed) and then hand it back to other components in my app.
How is this constructed ?
Once you have hooked up your redux store into your react application, using the approach recommended by #Abhisar. Your component automatically watches your state for changes and re-renders whenever there is a change in your redux state.
Also, see the official React Redux Doc
I believe you need to use connect and mapStateToProps for this requirement.
What we need to do is use connect function from react-redux, your component would look something like this -:
import { connect } from "react-redux";
import {Component} from "react";
class YourComponent extends Component {
constructor(props){
super(props);
this.state = props.data;
}
// Your component code.....
}
export const mapStateToProps = state => ({
data: state.data,
});
export default connect(mapStateToProps)(YourComponent);

Use same instance of socket across React application

The goal is to initiate a socket connection in App.js on app start and then make this exact socket instance available to other components that are loaded with Router. Online research suggests passing socket to a nested component as follows:
const socket = io();
...
render() {
return(<div className="App"><NestedComponent socket={socket} /></div>)
}
This does not work if socket is passed via Router
<Route path='/somepath' socket={socket} component={SomeComponent}/>
If I attempt using socket in SomeComponent (e.g.: this.props.socket.emit('hi', {})), this breaks app as socket turns out to be undefined in SomeComponent.
I was not able to look up a working solution to either pass same instance of a socket with a Router, or use Redux to make socket part of the app state and provide it to lower level components.
Any input on this is much appreciated.
You can use render method and pass the socket like this:
<Route path='/somepath'
render={(props) => (<SomeComponent socket={socket} {...props} />)} />
Notice: {...props} is being passed to access router props like location, history, match etc.
In SomeComponent:
// to access socket props
this.props.socket
So, this should work fine now:
this.props.socket.emit('hi', {})

React components not updating from Redux state after Hot Module Reload

I am using react-hot-loader 3.0.0-beta.6 to hot reload react components. Reloading itself works well - i see the updated component immediately. Unfortunately, after successful reload, dispatching actions inside the application does not trigger rerenders any more and I need to do a full manual refresh to get the application working again. The dispatched actions update the redux store, but the components are not rerendered.
All the components I am using consist of a connected container and a stateless component.
What could be the reason for not rendering the updated state? How could I continue debugging?
MyComponent/container.js:
const mapStateToProps = state => ({
...
});
const mapDispatchToProps = dispatch =>
bindActionCreators({
...
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(Component);
MyComponent/component.jsx:
const Component = ({ testProp1, testProp2 }) => (
<div onClick={testProp2}>
{testProp1}
</div>
);
Here is the successful update:
[WDS] App updated. Recompiling...
[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR] - ./source/modules/DropDown/index.js
...
[HMR] - ./source/modules/App/index.js
Render in the main.jsx:
const render = () => {
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<MuiThemeProvider>
<App />
</MuiThemeProvider>
</Provider>
</AppContainer>,
eyeTalLayer
);
};
render();
if (module.hot) {
module.hot.accept('./modules/App', render);
}
There's actually a couple open issues in the React-Redux repo discussing similar behavior as of React-Redux 5.0. See react-redux#636 and react-redux#670.
I did a bit of research, and it looks like the components higher in the hierarchy are getting recompiled and hot-reloaded, but not the components lower in the hierarchy. Because v5 implemented a top-down subscription system, the lower components aren't aware that their subscription references are now stale. I haven't had time yet to try to figure out a good way to handle that.
Based on what I've seen, I believe that removing the use of React-Hot-Loader will work around the problem. You could just reload the entire component tree using "plain" HMR, and I see you've already got your code set up to do that. You'd lose the potential benefits of RHL trying to maintain component state, but the Redux connections should reset properly.

Categories

Resources