I've seen an upgrade guide here how to use withRouter but I have a problem implementing it on my project. It's having problem with my connect. When I have my connect above withRouter, router exists on props but not my states, and when I have connect below withRouter, states exist but not router.
Here's my code:
import React from 'react';
import { withRouter } from 'react-router';
import moment from 'moment';
import { connect } from 'react-redux';
export default class ThisComponent extends React.Component {
render() {
console.log(this.props)
return ...
}
});
export default connect(state => ({ oneState: state.oneState, twoState: state.twoState }))(ThisComponent)
export default withRouter(ThisComponent)
Well you have 3 "export default" when you are supposed to have only one per file.
Your component should look like this
import React from 'react';
import { withRouter } from 'react-router';
import moment from 'moment';
import { connect } from 'react-redux';
class ThisComponent extends React.Component {
render() {
console.log(this.props)
return ...
}
});
ThisComponent = connect(state => ({ oneState: state.oneState, twoState: state.twoState }))(ThisComponent)
export default withRouter(ThisComponent)
Related
Just started using react and i am following a tutorial. I have the same code as him but i am getting the following error.
./src/index.js
Attempted import error: './components/App' does not contain a default export (imported as 'App')###
Here are my index and component file.
my index.js file
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(
<App/ >,document.getElementById('root')
)
my App.js
import React, {Component} from 'react';
class App extends Component {
render(){
return(
<div>Ageteller Component</div>
)
}
}
You need to export your App component.
Under the component put export default App
It should look like:
import React, {Component} from 'react';
class App extends Component {
render(){
return(
<div>Ageteller Component</div>
)
}
}
export default App
export the App Component
Try following
import React, {Component} from 'react';
export default class App extends Component {
render(){
return(
<div>Ageteller Component</div>
)
}
}
I'm following the Let’s Build: Cryptocurrency Native Mobile App With React Native + Redux tutorial.
When I create my store in App.js, the app works fine
import { createStore, applyMiddleware, compose } from 'redux';
import devTools from 'remote-redux-devtools';
import React, { Component } from 'react';
import { Platform, View } from 'react-native';
import { Provider } from 'react-redux';
import promise from 'redux-promise';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import { Header, CryptoContainer } from './src/components';
import rootReducer from './src/reducers';
const middleware = applyMiddleware(thunk, promise, logger);
const Store = createStore(rootReducer, compose(middleware, devTools({
name: Platform.OS,
hostname: 'localhost',
port: 5678
}), ));
export default class App extends Component {
render() {
return (
<Provider store={Store}>
<View>
<Header />
<CryptoContainer />
</View>
</Provider>
);
}
}
but when I move the store logic to a new file ./src/Store.js,
import { Platform } from 'react-native';
import { createStore, applyMiddleware, compose } from 'redux';
import devTools from 'remote-redux-devtools';
import promise from 'redux-promise';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import rootReducer from './reducers';
const middleware = applyMiddleware(thunk, promise, logger);
const Store = createStore(rootReducer,compose(middleware,devTools({
name: Platform.OS,
hostname: 'localhost',
port: 5678
}),
)
);
export default Store;
and use it in App.js like
import React, { Component } from 'react';
import { View } from 'react-native';
import { Provider } from 'react-redux';
import { Header, CryptoContainer } from './src/components';
import { Store } from './src/Store';
export default class App extends Component {
render() {
return (
<Provider store={Store}>
<View>
<Header />
<CryptoContainer />
</View>
</Provider>
);
}
}
I get
TypeError: undefined is not an object (evaluating 'store.getState')
What's causing my build (expo start) to fail when I import Store.js?
It seems the import statement is not right. It should be:
import Store from './src/Store';
if you're importing a single named export
e.g where you've done export const MyComponent = () => {} you'd import it like import { MyComponent } from "./MyComponent"
if you're importing a default export e.g where you've done const MyComponent = () => {} export default MyComponent you'd import it like import MyDefaultComponent from "./MyDefaultExport"
I got this error because I was exporting the wrong component from my main App file.
I was exporting this:
import React from 'react'
import { Provider } from 'react-redux'
import { createAppContainer } from 'react-navigation'
import Navigator from './src/components/Navigator'
import { store } from './src/store'
const App = createAppContainer(Navigator);
const Wrapped = props => (
<Provider store={store}>
<App />
</Provider>
)
export default Provider; // wrong!
That last line should be:
export default Wrapped; // right!
The answer from Itunu Adekoya shows that you can decide how you want to export / import, and in this case about personal preference, as there isn't a perf difference.
In the case where you have a lot of exports from a file, and perhaps some are unrelated or won't all be used together, it is better to export them individual as consts and then in other file only import what you need via import { } format, this will be sure to only include relevant imprts
in my case its casing & named import issue. imported as
import store from './Redux/Store'
it should be
import {Store} from './Redux/Store'
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?
The closest to doing this is reduxForm().getFormState() of which it's not well documented
You'll want to use the formValueSelector that is exported from redux-form. While you can dive directly into the state tree and pull things out for yourself, using the selector exported by redux-form means that you aren't taking a dependency on any implementation details of redux-form.
You use it like:
import React from 'react';
import { formValueSelector } from 'redux-form';
class App extends React.Component {
// ...
}
const formName = 'myForm'; // Name of form you want
const myFormValueSelector = formValueSelector(formName);
const mapStateToProps = state => ({
name: myFormValueSelector(state, 'name') // selects the name field value
});
export default connect(mapStateToProps)(App);
You can find documentation for this method here
Form values will be available on the redux store. You can get it from any app components.
Mini example,
index.js,
import React from 'react';
import ReactDOM from 'react-dom';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
import App from './src/components';
const rootReducer = combineReducers({
form: formReducer,
});
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const store = createStoreWithMiddleware(reducers);
ReactDOM.render(
<Provider store={store}>
<App />
<Provider>
, document.querySelector('.root'));
app.js,
import React, { Component } from 'react';
import { change, Field, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
class App extends Component {
...
render() {
console.log(this.props.forms); // This fill print information about all of your app forms
return <div />;
}
}
function mapStateToProps(state) {
return {
forms: state.form;
}
}
export default reduxForm({
form: 'someForm',
})(connect(
mapStateToProps,
null
)(App));
In app.js, console.log will print form data like this,
{
someForm: {...someForm props},
someOtherForm: {...someOtherForm props},
}
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.