React Redux - this.props.actions.fetchPosts is not a function - reactjs

i have issue with calling async action from my component, i think i did everything what was needed to work but seems like not, i used:
mapDispatchToProps
and inside i return
actions: bindActionCreators(fetchPosts, dispatch)
and i connect it.
After all these things, i try to call this action in my component -
this.props.actions.fetchPosts()
in result i get this error in console -
this.props.actions.fetchPosts is not a function
And i can not understand what's the problem with it as i did everything, here will be the full source:
Component
import React, { Component } from 'react';
import { Link } from 'react-router';
import styles from './Home.css';
import { fetchPosts } from '../actions/counter';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
class Home extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<div className="container">
<div className="banner_animated">
<p> dadasda</p>
</div>
</div>
<div className="container-fluid">
<div className="center">
<input type="text"/>
<button className="btn-2 btn-2a btn" onClick={this.props.actions.fetchPosts()}>Button</button>
</div>
</div>
</div>
);
}
}
function mapStateToProps(state) {
return state
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(fetchPosts, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Action
import { FETCHING_WIN_RATES, FETCHED_WIN_RATES } from '../const';
import { firebaseDb } from './firebase';
const ref = firebaseDb.ref("win_rate");
function fetchingWinRates() {
return {
type: FETCHING_WIN_RATES
};
}
function fetchedWinRates(winRates) {
return {
type: FETCHED_WIN_RATES,
winRates
};
}
// win rate champions
export function fetchPosts() {
return dispatch => {
dispatch(fetchingWinRates());
ref.on("value", function(snapshot) {
dispatch(fetchedWinRates(snapshot));
console.log(snapshot.val());
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
}
}
Write if you need some more files to help me, thank you.

If you pass a function to bindActionCreators, it will return a function. See the documentation for bindActionCreators here (in the Returns section): http://redux.js.org/docs/api/bindActionCreators.html.
You are effectively assigning this.props.action = fetchPosts here, meaning you would call fetchPosts like so: this.props.action().
If you want to access via this.props.actions.fetchPosts, you need to do the following:
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({ fetchPosts }, dispatch)
};
}
Notice the shorthand { fetchPosts } which is the same as { fetchPosts: fetchPosts }.

You don't need to use bindActionCreators http://redux.js.org/docs/api/bindActionCreators.html
const mapDispatchToProps = dispatch => ({
onClick: () => dispatch(fetchPosts(id))
})
}
and then access via this.props.onClick

Related

my mapdispatch to props is automatically calling

Post component:
import React from 'react';
import './post.styles.scss';
import { connect } from 'react-redux';
import { requestContents } from '../../redux/post/post.actions';
class Post extends React.Component {
componentWillMount(){
}
render(){
return (
<div>
</div>
)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onRequestContents : dispatch(requestContents())
}
}
const mapStateToProps = (state) => {
return {
posts: state.post.posts,
isPending: state.post.isPending
}
}
User component:
export default connect(mapStateToProps, mapDispatchToProps)(Post)
import React from 'react';
import './user.styles.scss';
import { connect } from 'react-redux';
import { requestUsers } from '../../redux/user/user.actions';
class User extends React.Component {
componentWillMount(){
this.props.onRequestUsers();
}
render(){
return (
<div>
</div>
}
}
const mapDispatchToProps = (dispatch) => {
return {
onRequestUsers: () => dispatch(requestUsers())
}
}
const mapStateToProps = (state) => {
return {
users: state.user.users,
isPending: state.user.isPending
}
}
export default connect(mapStateToProps, mapDispatchToProps)(User)
Here I am using redux with React.
In user component i am calling onRequestUsers inside componentWillMount()
but in post component i am not calling onRequestContents inside componentWillMount()
But still how it is calling and display in my redux-logger
I am calling mapDispatchToProps only inside user component
Please have a look
You're calling requestContents in your mDTP call:
const mapDispatchToProps = (dispatch) => {
return {
onRequestContents: dispatch(requestContents())
}
}
That's what those two parens do:
requestContents()
Omit them:
onRequestContents: dispatch(requestContents)
That said: there's something odd with your function. Normally you'd mDTP with a function, e.g.,
onRequestContents: () => dispatch(requestContents())
(Used when you need to pass parameters, like an event.)

Object(...) is not a function

I learning redux by following some tutorial. Here I am getting an error
Object(...) is not a function
in this line
export default connect(null, { fetchPosts } )(Posts);
of the following container
import React, { Component } from 'react';
import { connect } from 'react'
import axios from 'axios';
import { fetchPosts } from '../actions/postActions.js';
class Posts extends Component {
componentWillMount() {
this.props.fetchPosts();
}
render() {
const postItems = this.state.posts.map(el => {
return (
<div key={el.id}>
<h3>{el.title} </h3>
<p>{el.body} </p>
</div>
)
})
return (
<div>
<h1> Posts </h1>
{postItems}
</div>
);
}
}
export default connect(null, { fetchPosts } )(Posts);
Ps: I know it will also throw the map error but I am not worried about it at the moment.
Since it says Object(...) is not a function and marks the line export, the only object we have inside export is the fetchPosts which looks like this (it is an action function)
import { FETCH_POST, NEW_POST } from './type.js'
import axios from 'axios';
export const fetchPosts = () => {
return function (dispatch) {
axios.get("https://jsonplaceholder.typicode.com/posts").then((response) => dispatch({
type: FETCH_POST,
payload: response
}))
}
}
Since I am not sure the relevant code for the same, the fetchPosts dispatches an acton to the following reducer
import { FETCH_POST, NEW_POST } from '../actions/type.js'
const initialState = {
items: [],
item: {}
}
export default function(state = initialState, action) {
switch (action.type) {
case FETCH_POST:
return {
...state,
items: action.payload
}
default:
return state
}
}
Which is later combined using combineReducers in our rootreducer.js file (which is then imported to store.js where we create store)
Can Anyone tell me what I am doing wrong and How can we fix it?
React does not have a named connect export, it belongs to react-redux. So, you should import it like that:
import { connect } from "react-redux";

Why reducer does not respond to the action?

trying to make reducer works, but everytime "default" case fires.
Here is the code:
AC:
import {INPUT_IDEA_HANDLE} from "./types"
export function inputIdeaHandle(idea) {
console.log('it is working, I have access to the idea');
return {
type: INPUT_IDEA_HANDLE,
payload: idea
}
}
Reducer :
import {INPUT_IDEA_HANDLE} from "../actions/types"
export default function (state = null, action) {
switch (action.type) {
case INPUT_IDEA_HANDLE :
console.log('never fires');
return action.payload;
default:
console.log('fires everytime');
return state
}
}
import { combineReducers } from "redux";
import inputIdeaReducer from "./inputIdeaReducer.js"
export default combineReducers({
inputIdea: inputIdeaReducer
});
UPDATE
I changed my trigger code, but keep getting
Cannot read property 'props' of undefined
in return this.props.inputHandle(value);
Event trigger :
import React, { Component } from "react";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import { inputIdeaHandle } from "../actions";
class Dashboard extends Component {
changeHandle(e) {
e.preventDefault();
let value = e.target.value;
return this.props.inputHandle(value);
}
render() {
return (
<div className="dashboard container">
<div className="row">
<div className="col-12">
<h4>Type your idea here</h4>
<input
type="text"
onChange={this.changeHandle}
value={this.props.inputIdea}
/>
</div>
</div>
</div>
);
}
}
function mapStateToProps(state) {
return {
inputIdea: state.inputIdea
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
inputHandle: inputIdeaHandle
},
dispatch
);
}
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
Triple checked everything, but still keep getting 'fires everytime' in console. Count on you, guys
Regards
Issue is with handling this context.
You can handle this context as follows
constructor
constructor() {
super(props);
this.changeHandle = this.changeHandle.bind(this)};
}
Arrow function in render : onChange={e => this.changeHandle(e)}
React.createClass : React binds all functions to this.
Bind in render:
onChange={this.changeHandle.bind(this)}
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
you have to import your actions from your action file
import { postSelected } from '../containers/actions';
class Home extends Component {
changeHandle(e) {
e.preventDefault();
let value = e.target.value;
return this.props.post(value);
}
<input type="text" onChange={this.changeHandle} />
} //end of class
function mapStateToProps(state) {
return{
view: state.view
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
post: postSelected,
},dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
this should work edit it to suit your needs

Child component not connecting to store

I have a component that connects to a store and displays a child component like below:
render() {
return <div>
<div className="userBox">
<ProfilePhoto userid={this.props.id} />
</div>
<div className="nameTitleBox">
<div className="firstLastTitle">
<h1>{this.props.firstName} {this.props.lastName}</h1>
</div>
<IDBox userid={this.props.id} />
</div>
<div className="childcomponent">
<childComponent />
</div>
<div className="profileBox">
<EditInterests interestsList={this.props.interest} />
</div>
</div>
}
}
export default connect(
(state) => state.user,
UserState.actionCreators
)(User);
I want the child component to be a smart component that loads it's own data and controls everything itself. The code for it is pretty simple.
import * as React from 'react';
import { Link, RouteComponentProps } from 'react-router-dom';
import { ApplicationState } from '../../store';
import { connect } from 'react-redux';
import * as ChildState from '../../store/childStore';
export class ChildComponent extends React.Component {
componentWillMount() {
this.props;
}
render() {
return (<div>
<div className="textCenter"><h2 id="sss">{this.props.text}</h2></div>
<div className="textRight">
<input type="button" className="button" value="Yes" /> <b className="textColor">No</b>
</div>
</div>
</div>
</div>)
}
}
const mapDispatchToProps = (dispatch) => {
return {
action: dispatch(ChildState.actionCreators.requestChildren())
}
}
export default connect(
mapDispatchToProps,
ChildState.actionCreators
)(ChildComponent);
this.props in the child component is always an empty object. Nothing from the child state is in there, the initial state, the actions, dispatch...anything. I've tried a few different things. ChildState loads fine if I actually load it in the parent. Don't know why it's not loading in the child and connecting the props.
Adding the store below:
import { Action, Reducer } from 'redux';
import { fetch, addTask } from 'domain-task';
import { AppThunkAction } from './';
export const actionCreators = {
requestChildren: () => (dispatch, getState) => {
let url = 'random';
var myheaders = new Headers();
myheaders.append("X-Requested-With", "XMLHttpRequest");
let fetchTask = fetch(url, {
headers: myheaders,
credentials: "same-origin"
})
.then(response => response.json())
.then(data => {
dispatch({ type: 'POST_ACTION', children: data });
});
addTask(fetchTask);
}
}
export const initialState = { ... };
export const reducer = (state = initialState, incomingAction) => {
const action = incomingAction;
switch (action.type) {
case 'REQUEST_ACTION':
return {
...
};
case 'POST_ACTION':
return {
...
};
default:
}
return state || initialState;
};
I believe the problem is in mapDispatchtoProps have you tried using bindActionCreators
bindActionCreators make sure action (ChildState.actionCreators.requestChildren) flows through the middleware if there is any and then to the reducers
import { bindActionCreators} from 'redux';
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
ChildState.actionCreators.requestChildren}, dispatch); }
export default connect(
ChildState.actionCreators,
mapDispatchToProps
)(ChildComponent);
This was happening because I was exporting both the child component and the connect function. I removed the export on the child component and its working now as expected.

Dispatch Redux action in React

I'm trying to fetch test API using FetchAPI and Redux.
The problem is with dispatch redux action.
Here's my code:
ProductList.js
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as productActions from '../actions/product';
import RaisedButton from 'material-ui/RaisedButton';
function fetchProductsWithRedux() {
console.log("fetchProductsWithRedux-1");
return (dispatch) => {
console.log("fetchProductsWithRedux-2");
dispatch(this.props.action.fetchProdutcsRequest());
return fetchProdutcs().then(([response, json]) => {
if (response.status === 200) {
console.log("success");
dispatch(this.props.action.fetchProductsSucesss(json))
}
else {
console.log("error");
dispatch(this.props.action.fetchProductsError())
}
})
}
}
function fetchProdutcs() {
const URL = "https://jsonplaceholder.typicode.com/posts";
return fetch(URL, { method: 'GET' })
.then(response => Promise.all([response, response.json()]));
}
class ProductList extends Component {
constructor(props) {
super(props);
this.state = {
productList: [
'product 1',
'product 2',
'product 3'
]
}
}
componentDidMount() {
fetchProductsWithRedux();
}
render() {
return (
<div className="ProductList">
<h2>Products</h2>
<ul>
{
this.props.posts &&
this.props.posts.map((post) => {
return (
<li>{post.title}</li>
)
})
}
</ul>
<ol>
<RaisedButton label="Get Products Action" onClick={this.props.action.getProducts} />
</ol>
</div>
);
}
}
function mapStateToProps(state, props) {
return {
product: state.product,
posts: state.posts
};
}
function mapDispatchToProps(dispatch) {
return {
action: bindActionCreators(productActions, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ProductList);
product.js (actions)
export function fetchProductsRequest() {
console.log('fetchProductsRequest');
return {
type: 'FETCH_PRODUCTS_REQUEST'
}
}
export function fetchProductsSuccess(payload) {
console.log('fetchProductsSuccess');
return {
type: 'FETCH_PRODUCTS_SUCCESS'
}
}
export function fetchProductsError() {
console.log('fetchProductsError');
return {
type: 'FETCH_PRODUCTS_ERROR'
}
}
product.js (reducer)
export default(state = [], payload) => {
switch (payload.type) {
case 'FETCH_PRODUCTS_REQUEST':
console.log('FETCH_PRODUCTS_REQUEST action');
return state;
case 'FETCH_PRODUCTS_SUCCESS':
console.log('FETCH_PRODUCTS_SUCCES action');
return {...state, posts: payload.payload}
default:
return state;
}
};
store.js
import { createStore } from 'redux';
import rootReducer from './reducers';
export default(initialState) => {
return createStore(rootReducer, initialState);
}
Product.js (pages, component)
import React, { Component } from 'react';
import ProductList from '../../components/ProductList';
import RaisedButton from 'material-ui/RaisedButton';
//import './Product.css';
class Product extends Component {
render() {
return (
<div className="Product">
<h1>ProductList Page</h1>
<RaisedButton label="Default" />
<ProductList />
</div>
);
}
}
export default Product;
The line console.log("fetchProductsWithRedux-2"); in ProductList.js has never been reached.
What's wrong? Any ideas? Thanks in advance.
seem you missed import thunk from 'redux-thunk'. You can't return a function in redux action if you dont use any middleware like 'redux-thunk'
There are a few issues with your code.
Firstly, fetchProductsWithRedux is an action, so you would need to dispatch it rather than calling it directly. As Bjoern mentioned, the way you are calling it, the function call just returns a function, which is never called.
Now, you cannot dispatch it in the current scenario, as it returns a function, rather than object. To fix that, you will have to use redux-thunk, which will allow it to dispatch a function.
You can add it to mapDispatchToProps, as you did for getProducts, but there is a shorthand for that. In your mapDispatchToProps, you can do the following:-
const mapDispatchToProps = { fetchProductsWithRedux, getProducts }
You will notice that it is just returning an object with 2 functions.
From the documentation:
If an object is passed, each function inside it is assumed to be a Redux action creator. An object with the same function names, but with every action creator wrapped into a dispatch call so they may be invoked directly, will be merged into the component’s props.
So, it will do exactly what you did earlier with bindActionCreators, but it looks more elegant. Now, instead of onClick={this.props.action.getProducts}, you can do onClick={this.props.getProducts}. Notice the missing action.
Also, your import will change to
import { getProducts } from '../actions/product';
Now, to fix your issue, in componentDidMount, rather than calling the function directly, you will have to do:-
componentDidMount() {
this.props.fetchProductsWithRedux();
}
Hopefully, this will help.
function fetchProductsWithRedux() {
console.log("fetchProductsWithRedux-1");
return (dispatch) => {
console.log("fetchProductsWithRedux-2");
...
}
This returns a function function(dispatch){...}, which is not called in
componentDidMount() {
fetchProductsWithRedux();
}

Resources