ReactIntl work only when refreshing browser. - javascript

The translation only work on refresh. It seems because i have used a wrapper around the App.js that why its not working.
Also i tried to add a key to intlprovider the translation worked but now all my inner components get refresh.
Could there be a way to used reactintl when using an app wrapper without refreshing all inner components??
Below you can find the app.js, index.js and the app wrapper:
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './styles/global.css';
import registerServiceWorker from './registerServiceWorker';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import rootReducer from './redux/rootReducers';
import AppWrapperContainer from './containers/appWrapperContainer/appWrapperContainer';
import {localeSet} from './redux/actions/localeActions';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducer, /* preloadedState, */ composeEnhancers(
applyMiddleware(thunk)
));
if(localStorage.H24Lang)
{
store.dispatch(localeSet(localStorage.H24Lang));
}
ReactDOM.render((
<Provider store={store}>
<AppWrapperContainer/>
</Provider>
),
document.getElementById('root'));
registerServiceWorker();
AppWrapperContainer.js
import React, { Component } from 'react';
import { IntlProvider, addLocaleData} from "react-intl";
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import messages from '../../messages';
import en from "react-intl/locale-data/en";
import fr from "react-intl/locale-data/fr";
import App from "../../App";
addLocaleData(en);
addLocaleData(fr);
class AppWrapperContainer extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
const {lang} = this.props
let locale =
(navigator.languages && navigator.languages[0])
|| navigator.language
|| navigator.userLanguage
|| lang
return (
// <IntlProvider locale={lang} messages={messages[lang]} key={lang}></IntlProvider>
<IntlProvider locale={lang} messages={messages[lang]} >
<App/>
</IntlProvider>
);
}
}
AppWrapperContainer.propTypes = {
lang: PropTypes.string.isRequired
}
//what reducer you need
function mapStateToProps(state) {
console.log("State is", state);
return {
lang: state.locale.lang
};
}
export default connect(mapStateToProps,null)(AppWrapperContainer);
App.js
import React, { Component } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Home from './screens/home/home';
import { connect } from 'react-redux';
import { BrowserRouter as Router, Route,Redirect, Switch } from 'react-router-dom';
class App extends Component {
constructor(props) {
super(props);
this.state = {
};
}
componentWillMount() {
}
componentDidMount() {
}
render() {
return (
<div className="App">
<Router>
<div className = "app-main-content">
<Route exact path='/' component={Home} />
</Router>
</div>
);
}
}
//what reducer you need
function mapStateToProps(state) {
return {
};
}
function mapDispatchToProps(dispatch) {
return {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(App);

The key prop in IntlProvider forces React to remount the component (and all its children), but you just want them to be re-rendered (not remounted).
First confirm that your stored state is changing its locale/lang value as expected and that this change goes thougth mapStateToProps to your AppWrapperContainer component.
Then, make sure it is received in componentWillReceiveProps method and that a re-render is fired when its value changes. Then, all children will be re-rendered (if not blocked by shouldComponentUpdate method).
By the way, what is locale variable in AppWrapperContainer for?

Related

Redux store value set in callback

new to react-redux.I am facing a problem while working with redux store.
Data for store is loaded from API.Flow of my code is as follows:
app.js:
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Schema from './components/Schema';
import './styles/bootstrap.css';
import './styles/main.css';
export default class App{
constructor(props) {
super(props);
this.state = { store: {}};
}
componentWillMount(){
store(storeObject => {
this.setState({store: storeObject});
});
}
render(){
return <Provider store={ this.state.store }><Schema /></Provider>
}
}
store/index.js:
export default function(next) {
getInitialState(function(initialState) {
store = createStore(Reducers, initialState, compose(applyMiddleware(...middleware), extension));
console.log(store);//returning correct store value
next(store);
});
};
main.js:
import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import App from './app.js';
const dom = document.getElementById('root');
render(
<AppContainer>
<App />
</AppContainer>,
dom
);
it is giving following error.
The store function which I guess is a reference to the getStore function doesn't return anything which means that App doesn't return anything hence the exception.
Because getStore does an async operation, you'll have to do something like this:
export default class App extends Component{
componentWillMount(){
store(storeObject => {
this.setState({store: storeObject});
});
}
render(){
return <Provider store={ this.state.store }><Schema /></Provider>
}
}

reactjs router not rendering components

I have reactjs setup with routes but my routing is not working. When I load the page it works but when I click on the links the URL changes but the component does not render. I tried to put as much as I can in the sandbox. load with URL/admin and click on logout etc.
https://codesandbox.io/s/o5430k7p4z
index
import React, { Component } from 'react'
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { BrowserRouter, Route, browserHistory } from 'react-router-dom';
import promise from 'redux-promise';
import { createLogger } from 'redux-logger';
import App from './App'
import reducers from './reducers';
require("babel-core/register");
require("babel-polyfill");
import 'react-quill/dist/quill.snow.css'; // ES6
const logger = createLogger();
const initialState = {};
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App/>
</BrowserRouter>
</Provider>
, document.getElementById('root'));
App
import React, { Component } from 'react'
import { Switch, Route } from 'react-router-dom';
import ReactGA from 'react-ga';
ReactGA.initialize('UA-101927425-1');
import { connect } from 'react-redux';
import { fetchActiveUser } from './actions/index';
import { bindActionCreators } from 'redux';
import {getHttpRequestJSON} from './components/HTTP.js'
import Header from './components/header';
import Logout from './components/logout';
import SideBar from './components/sidebar';
import HomeContent from './containers/home';
import Ldapuser from './components/ldapuser';
import Admin from './components/admin/admin';
function fireTracking() {
ReactGA.pageview(window.location.pathname + window.location.search);
}
class App extends Component {
constructor(props){
super(props);
this.state = {
isGuest : false,
isSupp : false,
loading: true,
version: '',
};
}
initData = () => {
let self = this;
getHttpRequestJSON('/api/user/get/user/method/is/guest/format/json?quiet=1')
.then((response) => {
let isGuest = response.body.recordset.record.isGuest;
if(isGuest){
/*$(".logo").trigger('click');
//$("#overlay").show();
$('#modalIntro').modal('toggle');
$("#modalIntro").on("hidden.bs.modal", function () {
$(".logo").trigger('click');
});*/
}
self.props.isGuest = isGuest;
self.props.loading = false;
//self.props.version = response.header.version;
self.setState({
loading : false,
version : response.header.version,
isGuest : isGuest
});
})
.catch(error => {
console.log("Failed!", error);
//$('#myModalError .modal-body').html(error);
//$('#myModalError').modal('show');
});
getHttpRequestJSON('/api/user/get/user/method/is/supp/format/json?quiet=1')
.then((response) => {
self.setState({
isSupp : response.body.recordset.record.isSupp
});
})
.catch(error => {
console.log("Failed!", error);
//$('#myModalError .modal-body').html(error);
//$('#myModalError').modal('show');
});
}
componentDidMount() {
this.props.fetchActiveUser();
this.initData();
}
render() {
return (
<div>
<Header activeUser={this.props.activeUser} loading={this.state.loading} version={this.state.version} title={`Home`} />
<SideBar />
<main>
<Switch>
<Route path='/index.html' render={()=><HomeContent activeUser={this.props.activeUser} isGuest={this.state.isGuest} isSupp={this.state.isSupp} />} />
<Route path='/home' render={()=><HomeContent activeUser={this.props.activeUser} isGuest={this.state.isGuest} isSupp={this.state.isSupp} />} />
<Route path='/logout' component={Logout}/>
<Route path='/ldapuser' component={Ldapuser}/>
<Route path='/admin' render={()=><Admin isGuest={this.state.isGuest} isSupp={this.state.isSupp}/>} />
</Switch>
</main>
</div>
);
}
}
//export default App;
function mapStateToProps(state) {
if(state.activeUser.id > 0){
ReactGA.set({ userId: state.activeUser.id });
}
// Whatever is returned will show up as props
// inside of the component
return {
activeUser: state.activeUser
};
}
// Anything returned from this function will end up as props
// on this container
function mapDispatchToProps(dispatch){
// Whenever getUser is called, the result should be passed
// to all our reducers
return bindActionCreators({ fetchActiveUser }, dispatch);
}
//Promote component to a container - it needs to know
//about this new dispatch method, fetchActiveUser. Make it available
//as a prop
export default connect(mapStateToProps, mapDispatchToProps)(App);
The codesandbox is not working, but I think what is happening to you is a very common problem when using react-redux and react-router. The connect HOC of react-redux has a builtin SCU (shouldComponentUpdate), so for it to know to rerender is requires to receive new props. This can be done using the withRouter hoc of react-router. Simply wrap connect(..)(MyComponent) with withRouter(connect(..)(MyComponent)) or do it clean and use compose (from recomponse for example);
const enhance = compose(
withRouter,
connect(mapStateToProps)
)
export default enhance(MyComponent)
Make sure not to do it the other way around, because that does not work.

React-Router v4.2.2 not working (I think I've done something wrong in the Route tag?)

I'm using react-router v4.2.2 in my project, and am trying to create a set of cards that each link to other components. Right now I'm just testing that the router works, by routing each Card to one specific component called 'Project1'. This, however, is not working; I'm not seeing the div inside the Project1 component pop up. What am I doing wrong?? Shouldn't each Card link to the Project1 component?
Here is the code for the main container that holds the cards:
import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import ProjectCard from '../components/project_card.js';
import Project1 from '../components/project1.js';
class ProjectCards extends React.Component {
render() {
var projectCards = this.props.projects.map((project, i) => {
return (
<div key={i}>
<Link to={`/${project.title}`}>
<ProjectCard title={project.title} date={project.date} focus={project.focus}/>
</Link>
</div>
);
});
return (
<div>{projectCards}</div>
);
}
}
function mapStateToProps(state) {
return {
projects: state.projects
};
}
export default connect(mapStateToProps)(ProjectCards);
Here is the code for the Routes container:
import React from 'react';
import Project1 from '../components/project1.js';
import { connect } from 'react-redux';
import { Route, Switch } from 'react-router-dom';
class Routes extends React.Component{
render() {
var createRoutes = this.props.projects.map((project, i) => {
return <Route key={i} exact path={`/${project.title}`} component={Project1}/>
});
return (
<Switch>
{createRoutes}
</Switch>
);
}
}
function mapStateToProps(state) {
return {
projects: state.projects
};
}
export default connect(mapStateToProps)(Routes);
Here is the code for the index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { applyMiddleware, createStore } from 'redux';
import ReduxPromise from 'redux-promise';
import { BrowserRouter } from 'react-router-dom';
import App from './components/App.jsx';
import css from '../style/style.css';
import style from '../style/style.css';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
, document.getElementById('root'));
and the code for Project1, which should display when a Card has been clicked:
import React from 'react';
const Project1 = () => {
return (
<div>hello there this is Project1</div>
);
}
export default Project1;
When you click on a link, you navigate to Project1, which has no Routes defined. You basically destroy your Route when you lick on it because the Switch is in the same component as the Link. The Switch statement needs to be moved to a 3rd component so that it still exists after clicking on a linking card.

Uncaught TypeError: this.props.*** is not a function in React-redux app while calling a function from redux container

I have a react app with redux implemented and I'm getting this error
Uncaught TypeError: this.props.updateDimensions is not a function
while executing the App.js:-
class App extends Component {
componentDidMount() {
this.updateWindowDimensions();
window.addEventListener("resize", this.updateWindowDimensions);
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateWindowDimensions);
}
updateWindowDimensions() {
this.props.updateDimensions(window.innerWidth, window.innerHeight);
}
render() { .....
The AppContainer.js file:-
import { connect } from "react-redux";
import App from "./App";
import { UPDATE_DIMENSIONS } from "../actions";
const mapStateToProps = (state, ownProps) => {
return {
screenWidth: state.screenSize.screenWidth,
screenHeight: state.screenSize.screenHeight
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
return {
updateDimensions: (screenWidth, screenHeight) => {
dispatch({ type: UPDATE_DIMENSIONS, screenWidth, screenHeight });
}
};
};
const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App);
export default AppContainer;
This is the index.js, where the AppContainer is being called:-
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import rootReducer from "./reducers";
import { BrowserRouter as Router, Route } from "react-router-dom";
import "./index.css";
import AppContainer from "./App";
import registerServiceWorker from "./registerServiceWorker";
import "semantic-ui-css/semantic.min.css";
let store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<Router>
<Route component={AppContainer} />
</Router>
</Provider>,
document.getElementById("root")
);
registerServiceWorker();
I believe this is a common error and I have looked everywhere and there seems to be no obvious flaw in the code. Not sure where the issue is.
Figured it out.
in index.js:-
import AppContainer from "./App";
should be
import AppContainer from "./AppContainer";
ugh! This would have been so much easier if React threw an error saying 'AppContainer not found in ./App.js'
Update:-
I also had another error that was fixed by adding the following:-
constructor(props) {
super(props);
this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
}
I think you forgot :
constructor(props) {
super(props);
}

--How do I get access to my container/store in this top level file?

I'm just getting started with React/Redux and have everthing working fine with Redux when I test it.
However, I am not able to connect it into my actual application.
I assume I should use connect(), but I don't know how/where to.
// libraries
import React from 'react';
import ReactDOM from 'react-dom';
// redux
import { Provider } from 'react-redux';
import store from './redux/store';
import './redux/test.js';
import {connect} from 'react-redux'
class App extends React.Component {
constructor(props, test) {
super(props);
}
render () {
return (
<div id = 'contents'>
</div>
)
}
}
const app = document.getElementById('app');
ReactDOM.render(
<Provider store={store}>
<App></App>
</Provider>
, app);
You need to connect your component App.
By example let's assume you have value in your reducer named reducer in your store :
// libraries
import React from 'react';
import ReactDOM from 'react-dom';
// redux
import { Provider } from 'react-redux';
import store from './redux/store';
import './redux/test.js';
import {connect} from 'react-redux'
class App extends React.Component {
constructor(props, test) {
super(props);
}
render () {
// You can use data from props
return (
<div id = 'contents'>
{this.props.data}
</div>
)
}
}
const mapStateToProps = (state, ownProps) => {
// Bind your store state to the component data
return {
date: state.reducer.value,
};
}
const mapDispatchToProps = (dispatch) => {
// Bind actions to your component
}
const ConnectedApp = connect(mapStateToProps, mapDispatchToProps)(App);
const app = document.getElementById('app');
ReactDOM.render(
<Provider store={store}>
<ConnectedApp></ConnectedApp >
</Provider>
, app);
so what you need is to wrap App with the function returned by connect:
const AppWithRedux = connect()(App);
ReactDOM.render(
<Provider store={store}>
<AppWithRedux/>
</Provider>,
app);
But you can find a good example about how to integrate redux with react in the following link:
http://redux.js.org/docs/basics/UsageWithReact.html

Categories