Redux Form action undefined - javascript

I am trying to do authorization.
I get the data from reduxForm, and it is visible, but for some reason the data does not immediately get into the function, but goes to action, and I get an undefined value.
Registration is carried out on the same principle, but there are no errors.
Where could my mistake be?
REDUX
const NewUserEror = "NewUserEror";
const RegSucces = "RegSucces";
const RegStart = "RegStart";
const RegEnd = "RegEnd";
let initialState = {
error: null,
loading: false
};
const registrationReducer = (state = initialState, action) => {
switch (action.type) {
case RegSucces:
return {
...state,
error: false
};
case NewUserEror:
return {
...state,
error: action.payload
};
case RegStart:
return {
...state,
loading: true
};
case RegEnd:
return {
...state,
loading: false
};
default:
return state;
}
};
export const LogInUser = data => async (
dispatch,
getState,
{ getFirebase }
) => {
const firebase = getFirebase();
dispatch({ type: RegStart });
try {
await firebase.auth().signInWithEmailAndPassword(data.email, data.password);
dispatch({ type: RegSucces });
} catch (err) {
dispatch({ type: NewUserEror, payload: err.message });
}
dispatch({ type: RegEnd });
};
CONTAINER
import React from "react";
import { connect } from "react-redux";
import Login from "./login";
import LogInUser from "./../../../redux/registrationReducer"
class AuthBox extends React.Component{
Userlogin=(formdata)=>{
this.props.LogInUser(formdata)
}
render(){
return<Login {...this.props} Userlogin={this.Userlogin}></Login>
}
}
let mapStateToProps=(state)=>{
return{
loading:state.Regis.loading,
error:state.Regis.error
}
}
export default connect(mapStateToProps,{LogInUser})(AuthBox);
COMPONENT
const Login = props => {
let onSubmit = formData => {
props.Userlogin(formData);
};
return (
<div className={classes.formbox}>
<div className={classes.form}>
<h5 className={classes.formtitle}>Вход</h5>
<LoginForm onSubmit={onSubmit}></LoginForm>
</div>
</div>
);
};
export default Login;
Error
Action undefined
p.s sorry for my english

NON DEFAULT EXPORT MUST BE IN {}
import React from "react";
import { connect } from "react-redux";
import Login from "./login";
////// here
import {LogInUser} from "./../../../redux/registrationReducer"
////
class AuthBox extends React.Component{
Userlogin=(formdata)=>{
this.props.LogInUser(formdata)
}
render(){
return<Login {...this.props} Userlogin={this.Userlogin}></Login>
}
}
let mapStateToProps=(state)=>{
return{
loading:state.Regis.loading,
error:state.Regis.error
}
}
export default connect(mapStateToProps,{LogInUser})(AuthBox);

Related

React JS & Redux: Rendering Multiple Components within the Provider Throws an Undefined Error

I am working on this React JS Redux app where I have one store with 2 action files, 2 reducer files and 2 action type files. Everything works good when I am rendering only one component of these action files. If I render both as you see below, I get that the second component's object is undefined:
function App() {
return (
<Provider store={store}>
<div className="App">
< Posts />
< Users />
</div>
</Provider>
);
}
Rendering the above, throws the following error:
Cannot read property 'map' of undefined
If I render the above either omitting </ Posts> or </ Users> it works fine and it fetches the related data of each component.
Is it not possible to render two components within the Provider?
For more context, this is what I have in my application so for:
Store.js Includes:
import { createStore, compose, applyMiddleware, combineReducers } from
"redux";
import reduxThunk from "redux-thunk";
import postReducer from "../reducers/postReducer";
import userReducer from "../reducers/userReducer";
const rootReducer = combineReducers({
posts: postReducer,
users: userReducer
});
const store = createStore(rootReducer,
compose(applyMiddleware(reduxThunk)));
export default store;
App.js includes:
import './App.css';
import React from "react";
import store from './store/store.js';
import { Provider } from "react-redux";
import Posts from "./components/postComponent.js"
import Users from "./components/userComponent.js"
function App() {
return (
<Provider store={store}>
<div className="App">
< Posts />
< Users />
</div>
</Provider>
);
}
export default App;
actionTypes.js includes:
export const FETCH_POSTS_STARTED = 'FETCH_POSTS_STARTED';
export const FETCH_POSTS_SUCCESS = 'FETCH_POSTS_SUCCESS';
export const FETCH_POSTS_FAILURE = 'FETCH_POSTS_FAILURE';
export const FETCH_USERS_STARTED = 'FETCH_POSTS_STARTED';
export const FETCH_USERS_SUCCESS = 'FETCH_POSTS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_POSTS_FAILURE';
userAction.js includes:
import {
FETCH_USERS_STARTED,
FETCH_USERS_SUCCESS,
FETCH_USERS_FAILURE
} from '../actions/actionTypes';
import axios from "axios";
export const fetchUsers = () => {
return dispatch => {
dispatch(fetchUserStarted());
axios.get('https://jsonplaceholder.typicode.com/users')
.then(response => {
// dispatch response here
dispatch(fetchUserSuccess(response.data));
console.log('Data', response.data);
})
.catch(error => {
console.log('Error getting user API ' + error);
dispatch(fetchUserFailure(error.message));
})
}
}
const fetchUserStarted = () => {
return{
type: FETCH_USERS_STARTED,
payload: {
isLoading: true
}
}
}
const fetchUserSuccess = users => {
return{
type: FETCH_USERS_SUCCESS,
payload: {
users
}
}
}
const fetchUserFailure = error => {
return{
type: FETCH_USERS_FAILURE,
payload: {
error
}
}
}
postAction.js includes:
import {
FETCH_POSTS_STARTED,
FETCH_POSTS_FAILURE,
FETCH_POSTS_SUCCESS
} from "./actionTypes";
import axios from "axios";
export const fetchPosts = () => {
return dispatch => {
dispatch(fetchPostsStarted());
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then(res => {
dispatch(fetchPostsSuccess(res.data));
})
.catch(err => {
dispatch(fetchPostsFailed(err.message));
});
};
};
const fetchPostsStarted = () => {
return {
type: FETCH_POSTS_STARTED,
payload: {
isLoading: true
}
};
};
const fetchPostsSuccess = posts => {
return {
type: FETCH_POSTS_SUCCESS,
payload: {
posts
}
};
};
const fetchPostsFailed = error => {
return {
type: FETCH_POSTS_FAILURE,
payload: {
error
}
};
};
userReducer.js includes:
import {
FETCH_USERS_STARTED,
FETCH_USERS_SUCCESS,
FETCH_USERS_FAILURE
} from "../actions/actionTypes.js";
const initialState = {
users: [],
loading: false,
error: null
}
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_USERS_STARTED:
return {
...state,
loading: true
};
case FETCH_USERS_SUCCESS:
return {
...state,
loading: false,
error: null,
users: action.payload.users
};
case FETCH_USERS_FAILURE:
return {
...state,
error: action.payload.error
};
default:
return state
}
}
postReducer.js includes:
import {
FETCH_POSTS_STARTED,
FETCH_POSTS_SUCCESS,
FETCH_POSTS_FAILURE
} from "../actions/actionTypes.js";
const initialState = {
posts: [],
loading: false,
error: null
};
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_POSTS_STARTED:
return {
...state,
loading: true
};
case FETCH_POSTS_SUCCESS:
return {
...state,
loading: false,
error: null,
posts: action.payload.posts
};
case FETCH_POSTS_FAILURE:
return {
...state,
loading: false,
error: action.payload.error
};
default:
return state;
}
}
userComponents.js includes:
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchUsers } from "../actions/action.js";
class Users extends Component {
componentDidMount() {
this.props.fetchUsers();
}
render() {
const { users, loading, error } = this.props;
return (
<div>
{loading && <div>LOADING...</div>}
{error && <div>{error}</div>}
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
}
const mapStateToProps = state => {
const { users, loading, error } = state.users;
return {
users,
loading,
error
};
};
export default connect(
mapStateToProps,
{
fetchUsers
}
)(Users);
postComponents.js includes:
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchPosts } from "../actions/action.js";
class Posts extends Component {
componentDidMount() {
this.props.fetchPosts();
}
render() {
const { posts, loading, error } = this.props;
return (
<div>
{loading && <div>LOADING...</div>}
{error && <div>{error}</div>}
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
}
const mapStateToProps = state => {
const { posts, loading, error } = state.posts;
return {
posts,
loading,
error
};
};
export default connect(
mapStateToProps,
{
fetchPosts
}
)(Posts);
The problem is your action name constants. You copy-and-pasted from one to the other and forgot to change the names!
export const FETCH_POSTS_STARTED = 'FETCH_POSTS_STARTED';
export const FETCH_POSTS_SUCCESS = 'FETCH_POSTS_SUCCESS';
export const FETCH_POSTS_FAILURE = 'FETCH_POSTS_FAILURE';
export const FETCH_USERS_STARTED = 'FETCH_POSTS_STARTED';
export const FETCH_USERS_SUCCESS = 'FETCH_POSTS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_POSTS_FAILURE';
Since FETCH_USERS_SUCCESS is actually the same as FETCH_POSTS_SUCCESS, one type's fetch result is improperly updating the other type's state.
case FETCH_USERS_SUCCESS:
return {
...state,
loading: false,
error: null,
users: action.payload.users
};
Specifically, the error comes about because of the above case. When we set users to action.payload.users on a action which is actually of type 'FETCH_POSTS_SUCCESS', the value of action.payload.users is undefined. So now state.users.users is undefined instead of an array, and you get a fatal error when trying to call .map() on it.

I am getting TypeError: this.props.function is not a function while fetching from an api

I am trying to fetch data from an api, but I am getting an error: TypeError: this.props.getPeople is not a function, while everything looks good through the code, as below:
people-component.js
import React, { Component } from 'react';
import './people-component-styles.css';
import { Container, Row, Col, Card } from 'react-bootstrap';
import { connect } from 'react-redux';
import { getPeople } from '../../actions/index'
import 'react-lazy-load-image-component/src/effects/blur.css';
import 'animate.css/animate.min.css';
export class People extends Component {
componentDidMount() {
// console.log(this.props);
this.props.getPeople();
}
render() {
// console.log(this.props);
return (
<Row className='main'>
hello!
</Row>
);
}
}
const mapStateToProps = state => ({
people: state.people
})
const mapDispatchToProps = dispatch => ({
getPeople: () => dispatch(getPeople())
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(People);
actions/index.js
export const getPeople = () => {
console.log("yes");
return async dispatch => {
const response = await fetch('https://dma.com.eg/api.php?action=getPeople', {
method: 'GET'
})
const json = await response.json();
dispatch({ type: "GET_PEOPLE", payload: json });
}
}
reducers/index.js
const INITIAL_STATE = {
people: []
}
const rootReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case "GET_PEOPLE":
return ({
...state,
people: state.people.concat(action.payload)
})
default:
return state;
}
};
export default rootReducer
I was importing People component as name while it's exported as default, thanks to #Brian Thompson .. it's fixed.

How to Assign react redux state api get data using axios

i used react 16+ and redux get jsonplaceholder fake data to assign posts state but not working. can't assign the state. how can i assign json values into state using concat method. i check lifecycle methods also but can't get the answer.
Reducer
import * as actiontypes from './actions';
import axios from 'axios';
const initalstate = {
counter: 0,
posts: []
};
const reducer = (state = initalstate, action ) => {
switch (action.type) {
case actiontypes.actionFetchPost:
axios.get('https://jsonplaceholder.typicode.com/posts')
.then(res => {
return {
...state,
posts: state.posts.concat(res.data)
}
});
break;
default :
return state;
}
};
export default reducer;
Redux reducers must be pure functions, it means they should not contain any side effects like calling api.
You need to call api in action creators using redux-thunk package.
Codesandbox
An example action creator:
import {
FETCH_POSTS_STARTED,
FETCH_POSTS_FAILURE,
FETCH_POSTS_SUCCESS
} from "./actionTypes";
import axios from "axios";
export const fetchPosts = () => {
return dispatch => {
dispatch(fetchPostsStarted());
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then(res => {
dispatch(fetchPostsSuccess(res.data));
})
.catch(err => {
dispatch(fetchPostsFailed(err.message));
});
};
};
const fetchPostsStarted = () => {
return {
type: FETCH_POSTS_STARTED,
payload: {
isLoading: true
}
};
};
const fetchPostsSuccess = posts => {
return {
type: FETCH_POSTS_SUCCESS,
payload: {
posts
}
};
};
const fetchPostsFailed = error => {
return {
type: FETCH_POSTS_FAILURE,
payload: {
error
}
};
};
And reducer file:
import {
FETCH_POSTS_STARTED,
FETCH_POSTS_SUCCESS,
FETCH_POSTS_FAILURE
} from "../actions/actionTypes";
const initialState = {
posts: [],
loading: false,
error: null
};
export default function(state = initialState, action) {
switch (action.type) {
case FETCH_POSTS_STARTED:
return {
...state,
loading: true
};
case FETCH_POSTS_SUCCESS:
return {
...state,
loading: false,
error: null,
posts: action.payload.posts
};
case FETCH_POSTS_FAILURE:
return {
...state,
loading: false,
error: action.payload.error
};
default:
return state;
}
}
In store we use redux-thunk like this:
import { createStore, compose, applyMiddleware, combineReducers } from "redux";
import reduxThunk from "redux-thunk";
import postsReducers from "./reducers/postsReducers";
const rootReducer = combineReducers({
posts: postsReducers
});
const store = createStore(rootReducer, compose(applyMiddleware(reduxThunk)));
export default store;
Posts component:
import React, { Component } from "react";
import { connect } from "react-redux";
import { fetchPosts } from "./store/actions/postsActions";
class Posts extends Component {
componentDidMount() {
this.props.fetchPosts();
}
render() {
const { posts, loading, error } = this.props;
return (
<div>
{loading && <div>LOADING...</div>}
{error && <div>{error}</div>}
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
}
const mapStateToProps = state => {
const { posts, loading, error } = state.posts;
return {
posts,
loading,
error
};
};
export default connect(
mapStateToProps,
{
fetchPosts
}
)(Posts);
Index.js
import ReactDOM from "react-dom";
import store from "./store/store";
import { Provider } from "react-redux";
import Posts from "./Posts";
function App() {
return (
<div className="App">
<Posts />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
Do api call in action and return promise, use redux-thunk and redux-promise-middleware:
export const myApiCall = (args1, arg2) => async (dispatch, getState) => {
const payload = fetch({ ...config });
return dispatch({ type: 'MY_API_CALL', payload });
}
Then in reducer will have to handle two results:
MY_API_CALL_FULFILLED and MY_API_CALL_REJECTED

mapStateToProps returning undefined state from reducer

I am getting this error:
I have this reducer for async:
const initUserState = {
fetching: false,
fetched: false,
users: [],
error: null
};
const userReducer = (state = initUserState, action) => {
switch(action.type){
case "FETCH_USER":
state = {
...state,
users : action.payload
};
break;
case "FETCH_USER_START":
state = {
...state,
fetching: true
};
break;
case "FETCH_USER_SUCCESS":
state = {
...state,
fetched: true,
users: action.payload
};
break;
case "FETCH_USER_ERROR":
state = {
...state,
fetched: false,
error: action.payload
};
break;
default:
break;
}
return state;
};
export default userReducer;
And my container is:
import React from 'react';
import { Blog } from '../components/Blog';
import { connect } from 'react-redux';
//import { act_fetchAllUser } from '../actions/userActions';
import axios from 'axios';
class App extends React.Component {
componentWillMount(){
this.props.fetchAllUser();
}
render(){
console.log("Prop: " , this.props.user);
return(
<div>
<h1>My Blog Posts</h1>
<Blog/>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
user: state.userReducer
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchAllUser: () => {
dispatch((dispatch) => {
dispatch({ type: "FETCH_USER_START" })
axios.get('http://infosys.esy.es/test/get_allBlog.php')
.then((response) => {
dispatch({
type: "FETCH_USER_SUCCESS",
payload: response.data
});
})
.catch((err) => {
dispatch({
type: "FETCH_USER_ERROR",
payload: err
});
})
});
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
Im new to redux and I am into async now...
my application should load the users on page load but why my user state is returning undefined state? in the render method, i am logging the user props that contains the returned state from userReducer(mapStateToProps) but i am getting undefined. But when I getState() in store and log it, I am getting the expected result but it is not the ideal place to get the state right?... What i am doing wrong?
My store is:
import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger';
import userReducer from './reducers/userReducer';
import thunk from 'redux-thunk';
const store = createStore(userReducer,applyMiddleware(thunk, logger()));
//store.subscribe(() => console.log('State: ',store.getState()));
export default store;
And my index is:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './container/App';
import { Provider } from 'react-redux';
import store from './store';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider> , document.getElementById('root'));
Also, on my default case in userReducer, what should I code there.. should I just break; or do I need also to return state it? Thank you
You should have;
const mapStateToProps = (state) => {
return {
user: state.users
};
};
mapStateToProps passes state (global store) as a props to the component.
Global store
const initUserState = {
fetching: false,
fetched: false,
users: [],
error: null
};
inside component listening to user state
const mapStateToProps = (state) => {
return {
user: state.users
};
};

React redux display data from async action

I am building a react app and implementing redux for data. When I navigate to a particular route, I want to dispatch the action to fetch the data from an external API and then once the data comes back, display the data for the user.
Store :
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import createLogger from 'redux-logger';
import { syncHistoryWithStore } from 'react-router-redux';
import { browserHistory } from 'react-router';
import rootReducer from '../reducers/index';
const initialState = {
marvel :{
characters: []
}
};
const store = createStore(rootReducer, initialState, applyMiddleware(thunkMiddleware, createLogger()));
export const history = syncHistoryWithStore(browserHistory, store);
if (module.hot) {
module.hot.accept('../reducers/', () => {
const nextRootReducer = require('../reducers/index').default;
store.replaceReducer(nextRootReducer);
});
}
export default store;
reducer :
import * as constants from '../constants/constants';
const initialState = {
characters: [],
isFetching: false,
errorMessage: null
};
const marvelReducer = (state = initialState, action) => {
switch (action.type) {
case constants.FETCH_MARVEL :
return Object.assign({},state,{isFetching: true});
case constants.FETCH_MARVEL_SUCCESS :
return Object.assign({}. state,{
characters: [...action.response],
isFetching: false
});
case constants.FETCH_MARVEL_ERROR :
return Object.assign({}, state,{
isFetching: false,
errorMessage: action.message
});
default :
return state;
}
};
export default marvelReducer;
actions:
import 'whatwg-fetch';
import * as constants from '../constants/constants';
export const fetchMarvel = (dispatch) => {
const MARVEL_API = 'http://gateway.marvel.com:80/v1/public/characters?apikey=e542b1d89f93ed41b132eda89b9efb2c';
dispatch({
type: constants.FETCH_MARVEL
});
return fetch(MARVEL_API).then(
response => {
dispatch({
type: constants.FETCH_MARVEL_SUCCESS,
response
});
},
error => {
dispatch({
type: constants.FETCH_MARVEL_ERROR,
message: error.message || 'Something went wrong with fetchMarvel'
});
});
};
component :
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actions from '../actions/actions';
import '../styles/homeStyles.css';
class Home extends Component {
render() {
const { characters, isFetching, errorMessage } = this.props;
return (
<div>
<h1>React Starter App</h1>
<h2>This is the home page</h2>
</div>
);
}
}
function mapStateToProps(state) {
return {
characters: state.characters,
isFetching: state.isFetching,
errorMessage: state.errorMessage
};
}
function mapDispatchToProps(dispatch) {
return { actions: bindActionCreators(actions, dispatch) };
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
I know I'm not currently displaying the props anywhere in the application, but first I am just trying to get them populated.
What step am I missing to dispatch the action so that I can populate the props from state?
You are not dispatching the action anywhere. So nothing happens.
You probably want to do this in a React lifecycle hook, for example:
class Home extends Component {
componentDidMount() {
this.props.actions.fetchMarvel();
}
render() {
const { characters, isFetching, errorMessage } = this.props;
return (
<div>
<h1>React Starter App</h1>
<h2>This is the home page</h2>
</div>
);
}
}

Categories

Resources