face error when trying to render my code with redux part . dispatch a string from a file but not getting it on app.js - redux

REDUX RENDERING ERROR
face error when trying to render my code with the redux part. Successfully dispatch a string from a file but not getting it on app.js
import React from 'react';
import {Route, BrowserRouter} from 'react-router-dom'
import {connect} from 'react-redux'
import Home from './components/home'
import Data from './components/data'
import Nav from './components/nav'
import './App.css';
function App(props) {
const data = this.props.data //error in this line
return (
<div className="App">
<BrowserRouter>
<Nav />
<Route path='/' exact component={Home} />
<Route path='/data' component={Data} />
</BrowserRouter>
</div>
);
}
const mapStateToProps=(state)=>{
return {
data : state.data
}
}
export default connect(mapStateToProps)(App);

You are using functional component, so you have to get props direct without this
const data = props.data

Related

How to setup react-redux-firestore in NEXT.JS

I am migrating from my Create React App (client-side-rendering) to Next JS (server-side rendering) due to SEO reasons. Migrating was going well until using React-Redux-Firebase / Firestore. This is the page I am trying to load:
Discover.js
import React, { Component } from 'react'
import { firestoreConnect, isEmpty } from 'react-redux-firebase';
import { compose } from 'redux'
import { connect } from "react-redux";
import { blogpostsQuery } from '../blogposts/blogpostsQuery';
import DiscoverList from "./DiscoverList";
const mapState = (state, ownProps) => {
let blogposts = {};
blogposts =
!isEmpty(state.firestore.ordered.blogposts) &&
state.firestore.ordered.blogposts;
return {
blogposts,
};
};
class DiscoverPage extends Component {
render() {
const {blogposts} = this.props
return (
<div className="container">
<div className="hero">
<h1>Discover stories</h1>
<p className="lead">Blogpost published:</p>
</div>
<DiscoverList blogposts={blogposts} />
</div>
)
}
}
export default compose(
firestoreConnect(() => blogpostsQuery()),
connect(mapState, null)
)(DiscoverPage)
The error I received is this:
ReferenceError: XMLHttpRequest is not defined
at Rn.ca (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:36966)
at Ie (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:18723)
at Se (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:18385)
at Kn.a.Ia (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:39600)
at jt (/Users/fridovandriem/timepath/node_modules/firebase/firebase-firestore.js:1:15360)
error Command failed with exit code 1.
I wasn't the only one with this problem and I have found the solution on GitHub by prescottprue:
https://github.com/prescottprue/react-redux-firebase/issues/72
Including documentation: http://react-redux-firebase.com/docs/recipes/ssr.html
// needed to fix "Error: The XMLHttpRequest compatibility library was not found."
global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
The problem is (sorry i am new developer) I have no idea where to add this line of code? Adding it to _app.js doesnt work.. i've added https://www.npmjs.com/package/xmlhttprequest but still no luck...
-app.js
import App from "next/app";
import { Provider } from "react-redux";
import React, { Fragment } from "react";
import withRedux from "next-redux-wrapper";
import "../src/styles.css";
import configureStore from "../src/app/store/configureStore";
import Header from "../src/app/layout/Header";
import NavBar from "../src/app/layout/nav/Navbar/NavBar";
import Footer from "../src/app/layout/Footer";
global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
//Anything returned here can be accessed by the client
return { pageProps: pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
return (
<Fragment>
<Header />
<NavBar />
<Provider store={store}>
<Component {...pageProps} />
</Provider>
<Footer />
</Fragment>
);
}
}
export default withRedux(configureStore)(MyApp);
Could somebody help me?
Many thanks
Frido

Why is component not connecting to the redux store?

I am trying to connect some component (USERS) to my store. I will show you each step.
First of all i create my store in index.js:
// composeWithDevTools helps to follow state changes, remove in production
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const sagaMiddleware = createSagaMiddleware();
const store = createStore(reducers, composeEnhancers(applyMiddleware(sagaMiddleware)));
//sagaMiddleware.run(usersSaga);
console.log('MYSTORE: ', store);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
);
My reducer is coded in the following way:
import { combineReducers } from 'redux';
import usersReducer from './usersReducer';
export default combineReducers({
users: usersReducer,
});
Now my App.js file looks like this:
import React from 'react';
import { HashRouter, Route, Redirect } from 'react-router-dom';
import { AuthorisationMails } from './route-components/AuthorisationMails.js';
import { ChangePassword } from './route-components/ChangePassword.js';
import { Credits } from './route-components/Credits.js';
import { Graphs } from './route-components/Graphs.js';
import { Groups } from './route-components/Groups.js';
import { HeaderBar } from './components/HeaderBar.js';
import { Home } from './route-components/Home.js';
import { Login } from './route-components/Login.js';
import { MailServers } from './route-components/MailServers.js';
import { MailStatus } from './route-components/MailStatus.js';
import { Options } from './route-components/Options.js';
import { StatusMails } from './route-components/StatusMails.js';
import { Users } from './route-components/Users.js';
const App = () => (
<div>
<HashRouter>
<HeaderBar />
<Route path="/">
<Redirect to="/login" />
</Route>
<Route path="/login" component={Login} />
<Route path="/dashboard_user" component={Users} />
</HashRouter>
</div>
);
export default App;
In Users, i try to connect to the store with a mapstateToProps and connect as you see here:
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import * as actions from '../redux/actions';
export class Users extends Component {
componentDidMount() {
console.log('USERPROPS: ', this.props);
}
render() {
return <div>Users</div>;
}
}
const mapStateToProps = state => {
console.log('USERSSTATE: ', state.user);
return {
users: state.userReducer,
};
};
export default withRouter(connect(mapStateToProps)(Users));
The problem here is that somehow i am connecting in the wrong way, since the console.log of USERPROPS does not contain a property user. It contains history location and match.
I tried connecting by using the following url https://react-redux.js.org/api/connect.
Any idea on why my component is not connecting to the store?
Solved it, i removed the brackets when importing components, thus for example:
import { Credits } from './route-components/Credits.js' => import Credits from './route-components/Credits.js'
I think you might need to use state.users.user:
const mapStateToProps = state => {
return {
users: state.users.user,
};
};

React-Router Switch causing the current route to re-mount whenever redux state changes

I am using React-Router v4. However, whenever my applications Redux state is updated, React-Router's Switch component is updating and re-mounting the current route.
I define my HashRouter at in the main index.js file, like so:
/* global document */
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { HashRouter } from 'react-router-dom'
import App from './screens/app/index'
import registerServiceWorker from './registerServiceWorker'
import './styles/main.css'
import store from './store'
ReactDOM.render(
<Provider store={store}>
<HashRouter>
<App />
</HashRouter>
</Provider>,
document.getElementById('root'),
)
registerServiceWorker()
This is my component using the Switch component:
import PropTypes from 'prop-types'
import React from 'react'
import { Route, Switch } from 'react-router-dom'
const propTypes = {
routes: PropTypes.arrayOf(PropTypes.shape({
path: PropTypes.string,
name: PropTypes.string,
container: PropTypes.object,
exact: PropTypes.bool,
})).isRequired,
}
const Router = ({ routes }) => (
<Switch>
<div className="container">
{routes.map(route => (
<Route
key={route.path}
path={route.path}
exact={route.exact}
component={() => route.container}
/>
))}
</div>
</Switch>
)
Router.propTypes = propTypes
export default Router
And finally, I setup my store here:
import { createStore } from 'redux'
import reducer from './reducers/index'
export default createStore(reducer)
I was thinking possible issues could be:
There an issue with my Redux setup that is causing a collision with the redux store
The Routes aren't defined correctly
I suspect this is the line that remounts the component everytime
component={() => route.container}
try
const Router = ({ routes }) => (
<Switch>
<div className="container">
{routes.map(route => {
const routerComp = () => route.container
return (
<Route
key={route.path}
path={route.path}
exact={route.exact}
component={routerComp}
/>
)
})}
</div>
)

How to navigate to a url with different 'id' property using axios library in redux

I am working on a redux project where I have a list of posts(like Blog Post) and each post has an unique id.Also,I have a different component which displays the detail of a particular post(I have named it Post_Detail component). So what I want to do is when I click on a particular post from the list of posts,I want to navigate to the page which displays the detail of that particular post.
My action creator for displaying a selected post is:
//Action Creator for displaying a selected post
export function fetchPost(id) {
const request = axios.get(`${API}/posts/${id}`,{headers});
return dispatch => {
return request.then(({data}) => {
console.log(data);
dispatch({
type: FETCH_POST,
payload: data
})
})
}
}
My Post_Detail component for displaying the selected post is:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchPost, deletePost } from '../actions/posts_action';
class PostDetail extends Component {
componentDidMount() {
const { id } = this.props.match.params;
this.props.fetchPost(id);
console.log(id)
}
//Function for deleting on click using action creator
onDeleteClick() {
const { id } = this.props.match.params;
this.props.deletePost(id, () => {
this.props.history.push('/');
});
}
render() {
const { post } = this.props;
if (!post) {
return <div>Loading...</div>
}
return(
<div>
<div>
<h3>{post.title}</h3>
<h6>Categories: {post.category}</h6>
<p>{post.body}</p>
</div>
<button
className="btn btn-danger pull-xs-right"
onClick={this.onDeleteClick.bind(this)} >
Delete Post
</button>
</div>
);
}
}
function mapStateToProps({ posts }, ownProps) {
return { post: posts[ownProps.match.params.id] };
}
export default connect(mapStateToProps, { fetchPost, deletePost })(PostDetail);
My homepage for listing all the available posts is:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { BrowserRouter, Route } from 'react-router-dom';
import thunk from 'redux-thunk';
import './index.css';
import App from './App';
import reducers from './reducers/index.js'
import Posts from './components/posts_index';
import CreatePost from './components/new_post';
import PostDetail from './components/post_detail';
import CategoryView from './components/category';
import { compose } from 'redux';
import { Link } from 'react-router-dom';
//const createStoreWithMiddleware = createStore(reducers,applyMiddleware(thunk));
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const createStoreWithMiddleware = createStore(reducers, composeEnhancers(applyMiddleware(thunk)));
ReactDOM.render(
<Provider store={createStoreWithMiddleware}>
<BrowserRouter>
<div>
<Route path="/new" component={CreatePost} />
<Route path="/posts/:id" component={PostDetail} />
<Route exact path="/" component={Posts} />
<Route path="/:category/posts" component={CategoryView} />
</div>
</BrowserRouter>
</Provider> , document.getElementById('root'));
So, what is happening now is if I try to navigate to the post using the "id" for that post in the url like : http://localhost:3000/posts/8xf0y6ziyjabvozdd253nd where "8xf0y6ziyjabvozdd253nd" is the id of that post,I can navigate to the Post_Detail component and see the details of that post.But,I am not able to figure out how to navigate to the Post_Detail component when the post is clicked from the list of posts in the homepage. I know that I should use a "Link" from 'react-router-dom' and navigate to the page passing in the url in "to" property of the link, but I don't know how to dynamically change the id in the link. Can anyone please guide me how to proceed?

React Router v4 + Meteor createContainer - routes not rendering

I'm experiencing an issue using Meteor's createContainer with React Router v4. I've used it successfully with v3, but when I try to set up routing with v4 it loads the Main route and then won't render anything else. If I change App to a functional stateless component and bypass the data layer, the routing works fine, so I know it's something in there.
App.jsx:
import React from 'react'
import {Navigation} from './Navigation'
import {Grid, MenuItem} from 'react-bootstrap'
import {LinkContainer} from 'react-router-bootstrap'
import { createContainer } from 'meteor/react-meteor-data'
import {Products} from '../api/products'
import {Main} from './Main'
class App extends React.Component {
render () {
const {ready, products} = this.props;
if (!ready) return <h1>Loading...</h1>
const vendorsList = [...new Set(products.map(item => item.vendor).filter(i => !!i))]
const vendors = vendorsList.map((item, index) => <LinkContainer key={index} to={`/vendors/${item}`}><MenuItem eventKey={(index+1) / 10 + 4}>{item}</MenuItem></LinkContainer>)
return (
<div>
<Navigation vendors={vendors} />
<Grid>
<Main products={products} />
</Grid>
</div>
)
}
}
export default createContainer(({params}) => {
const handle = Meteor.subscribe('products');
return {
ready: handle.ready(),
products: Products.find({}, {sort: {name: 1}}).fetch()
};
}, App);
Navigation.jsx:
import React from 'react'
import {NavLink} from 'react-router-dom'
import {Navbar, Nav, NavItem, NavDropdown, MenuItem} from 'react-bootstrap'
import {LinkContainer} from 'react-router-bootstrap'
export const Navigation = ({vendors}) => (
<Navbar>
<Navbar.Header>
<LinkContainer to='/'><Navbar.Brand>IM 0.1</Navbar.Brand></LinkContainer>
</Navbar.Header>
<Nav>
<NavDropdown eventKey={1} title='Products' id='basic-nav-dropdown'>
<LinkContainer to='/products'><MenuItem eventKey={1.1}>Products List</MenuItem></LinkContainer>
<LinkContainer to='/products/new'><MenuItem eventKey={1.2}>Enter New Product</MenuItem></LinkContainer>
</NavDropdown>
<NavItem eventKey={2}>Inventory</NavItem>
<NavDropdown eventKey={3} title='Invoices' id='basic-nav-dropdown'>
<MenuItem eventKey={3.1}>Enter New Invoice</MenuItem>
<MenuItem divider />
<MenuItem eventKey={3.2}>Manage Invoices...</MenuItem>
</NavDropdown>
<NavDropdown eventKey={4} title='Vendors' id='basic-nav-dropdown'>
{vendors}
<MenuItem divider />
<MenuItem eventKey={(vendors.length + 1)/10 + 4}>Vendors List...</MenuItem>
</NavDropdown>
</Nav>
</Navbar>
)
main.js:
import React from 'react'
import { Meteor } from 'meteor/meteor'
import { render } from 'react-dom'
import {BrowserRouter} from 'react-router-dom'
import App from '../imports/ui/App'
Meteor.startup(() => {
render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('render-target'));
});
I know I'm missing something that's probably super basic, and it's driving me nuts. Thanks.
Try wrapping App.jsx with withRouter
Also note that Meteor createContainer function has been replaced by withTracker
import React from 'react'
import { withTracker } from 'meteor/react-meteor-data';
import { withRouter } from 'react-router-dom';
...
class App extends React.Component {
...
}
export default withRouter(withTracker(({params}) => {
...
})(App));

Resources