So I do this in container:
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators({fetchMarkers}, dispatch)
}
}
and when props is logged in browser I get:
actions: {
fetchMakers: function() ....
}
but when I call this.props.actions.fetchMarkers(params) I get the following error:
Cannot read property 'fetchMarkers' of undefined
This is driving me nuts, Please help!
Edit:
Action:
export const fetchMarkers = (payload) => {
return {
type: actionTypes.fetchMarkers,
payload
}
}
Try this case:
import { fetchMarkers } from 'path_to_makers_action';
....Code of react component....
export default connent(null, { fetchMarkers });
And in component you use: this.props.fetchMarkers()
Related
I've been trying to dispatch a function that will call an async parse cloud function. It worked well in my other projects when i used them in functions. But this is the first time i'm using them in a component and when i call the dispatch from map dispatch to props, I get this error. Please help me out.
ProfileHeader.js
import React, { Component } from 'react';
import Cover_Image from './Cover_Image.jpg';
import Profile_Pic from './Profile_Pic.svg';
import './ProfileHeader.css';
import { connect } from 'react-redux';
import { fetchUserProfile } from '../../Redux/UserProfile-Redux/UserProfileActionMethods';
class ProfileHeader extends Component {
componentDidMount() {
this.props.fetchUserProfile()
}
render() {
return (
<div className="profile-header-layout"></div>
)
}
}
const mapStatetoProps = (state) => {
return {
profile: state.UserProfile
}
}
const mapDispatchtoProps = (dispatch) => {
return {
fetchUserProfile: () => { dispatch(fetchUserProfile()) }, dispatch,
}
}
export default connect(mapDispatchtoProps, mapStatetoProps)(ProfileHeader)
The action Method:
import Parse from 'parse/dist/parse.min.js';
import { FETCH_USERPROFILE_FAILURE, FETCH_USERPROFILE_REQUEST, FETCH_USERPROFILE_SUCCESS } from './UserProfileActions';
const params = { username: "prvnngrj" }
export const fetchUserProfileRequest = () => {
return {
type: FETCH_USERPROFILE_REQUEST
}
}
export const fetchUserProfileSuccess = (userprofiles) => {
return {
type: FETCH_USERPROFILE_SUCCESS,
payload: userprofiles
}
}
export const fetchUserProfileFailure = (error) => {
return {
type: FETCH_USERPROFILE_FAILURE,
payload: error
}
}
export const fetchUserProfile = () => {
return async dispatch => {
dispatch(fetchUserProfileRequest)
try {
const responsedata = await Parse.Cloud.run("GetUserProfileForUsername", params);
const userprofiles = responsedata;
dispatch(fetchUserProfileSuccess(userprofiles))
}
catch (error) {
const errorMessage = error.message
dispatch(fetchUserProfileFailure(errorMessage))
}
}
}
Please ignore parts of code which do not make it relevant, its straight from the project
You mixed up the order of your arguments, so this.props.dispatch is actually your state!
You need to change
export default connect(mapDispatchtoProps, mapStatetoProps)(ProfileHeader)
to:
export default connect(mapStatetoProps, mapDispatchtoProps)(ProfileHeader)
If you can switch to function components and the useSelector/useDispatch hooks you should. This is the current recommended approach and it's easier to use.
I have following Action:
import axios from 'axios';
export function getAPIData(id)
{
return (dispatch) =>
{
axios.get('http://localhost:5000/api/' + id)
.then(res =>
{
dispatch(
{
type: 'DONE',
payload: res.data
});
});
}
}
Then in my Component I`m dispatching the action:
componentDidMount()
{
this.props.dispatch(getAPIData());
}
And then:
function mapStateToProps(state)
{
console.log(state);
return {
data: state.result
};
}
export default connect(mapStateToProps)(Rows);
In console, when I try to find the payload, it says what is bellow.
function()
arguments: TypeError: 'arguments', 'callee', and 'caller' cannot be
accessed in this context.
caller: TypeError: 'arguments', 'callee', and 'caller' cannot be
accessed in this context.
length: 1
name: ""
Where is problem? Thanks a lot.
to dispatch an action you need to provide mapDispatchToProps .
First import your action
import { getAPIData } from "../store/actions/getAPIData";
then build mapDispatchToProps
const mapDispatchToProps = (dispatch) => {
return {
getAPIData: (props = null) => {
dispatch(getAPIData(props));
},
};
};
add this alongside mapStateToProps
export default connect(mapStateToProps , mapDispatchToProps)(Rows);
now you can call the action like this
componentDidMount()
{
this.props.getAPIData();
}
I'm actually working on a small react app, i have an action to check if the current user exist in on the firestore collection 'users' based on the uid, anad then get the user’s profile information.
It works actually this action, but i can't use it in my profile component to display it !
That's the action file:
import 'firebase/firestore'
import firebase from 'firebase/app'
const getUser =()=>{
return (dispatch)=>{
firebase.auth().onAuthStateChanged(firebaseUser => {
if(firebaseUser){
firebase.firestore().collection("users").doc(firebaseUser.uid).get().then( doc => {
const { displayName } = doc.data()
//it works and it shows me on console the name i want
console.log("display name in action: ",displayName)
const currentUser = {
uid: firebaseUser.uid,
displayName
}
dispatch({
type:'GET_USER',
currentUser,
})
})
}
})
}
}
export default getUser ;
when i try to console log it in my profile file, it shows this error "typeError: undefined is not an object (evaluating 'this.props.getUser().currentUser')":
console.log("getting current user: ", this.props.getUser().currentUser )
I expect to display me the displayName but i got that error!
You actually looking for reducer. Action handler is not designed to return data to your component. Action idea is to store data to reducer.
Code below assumes that you have properly connected react-redux with your application.
src/actions/userAction.js
import 'firebase/firestore'
import firebase from 'firebase/app'
export const getUser = () => {
return (dispatch) => {
firebase.auth().onAuthStateChanged(firebaseUser => {
if (firebaseUser) {
firebase.firestore().collection("users").doc(firebaseUser.uid).get().then(doc => {
const {displayName} = doc.data();
const currentUser = {
uid: firebaseUser.uid,
displayName
};
dispatch({
type: 'GET_USER',
payload: currentUser
});
})
}
})
}
};
src/reducers/userReducer.js
const INITIAL_STATE = {
data: {},
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case 'GET_USER':
return {
...state,
data: action.payload
};
default:
return state;
}
};
src/reducers/index.js
import userReducer from "./userReducer";
export default {
user: userReducer
};
src/components/Example.js
import React from 'react';
import connect from "react-redux/es/connect/connect";
import {getUser} from "../actions/userAction";
class Example extends React.Component {
componentDidMount() {
this.props.getUser();
}
render() {
if (!Object.keys(this.props.user.data).length)
return <div>Loading user's data</div>;
return (
<div>
{ JSON.stringify(this.props.user.data) }
</div>
);
}
}
const mapStateToProps = (state) => {
return {
user: state.user
};
};
export default connect(mapStateToProps, {
getUser,
})(Example);
Looking for guidance using redux-token-auth. Throwing this Type Error:
Error
All the creators' examples involve making the calls from the Component class like so:
// EXAMPLE: components/SignInScreen.jsx
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { signInUser } from '../redux-token-auth-config' // <-- note this is YOUR file, not the redux-token-auth NPM module
class SignInScreen extends Component {
constructor (props) { ... }
...
submitForm (e) {
e.preventDefault()
const { signInUser } = this.props
const {
email,
password,
} = this.state
signInUser({ email, password }) // <-<-<-<-<- here's the important part <-<-<-<-<-
.then(...)
.catch(...)
}
render () {
const { submitForm } = this
<div>
<form onSubmit={submitForm}>...</form>
</div>
}
}
export default connect(
null,
{ signInUser },
)(SignInScreen)
Is it feasible to move the calls up to an action file? In documentation, he mentions that
registerUser, signInUser, and signOutUser are Redux Thunk actions and
thus, when wired through mapDispatchToProps return Promises.
I'm digging through the source code, but I can't figure out what changes when the sign in dispatch is mapped via Redux rather than directly imported and called. If anyone is familiar with this extension, any ideas would be much appreciated!
This is my attempt that throws the error:
// /actions/auth.js
import { signInUser, signOutUser } from '../redux-token-auth-config'
export const Login = (email, password) => {
return (dispatch) => {
dispatch(LoginStart());
signInUser({ email, password })
.then((response) => dispatch(LoginSuccess(response.data.data)))
.catch((error) => dispatch(LoginError(error)));
};
};
export const LoginStart = () => ({
type: 'LOGIN::START'
});
export const LoginSuccess = (data) => ({
type: 'LOGIN::SUCCESS',
payload: data
});
export const LoginError = (error) => ({
type: 'LOGIN::ERROR',
payload: error
})
export const Logout = () => {
return (dispatch) => {
dispatch(SessionCleanup())
signOutUser()
.then((response) => console.log('Success'))
.catch((error) => console.log(error))
}
}
export const SessionCleanup = () => ({
type: 'LOGIN::SESSION_CLEANUP'
})
Assuming you are trying to call Login from a component I had the same issue and fixed it by doing the following:
export default connect(state => ({}), { signInUser })(FooBar);
When I called the action I passed along signInUser.
this.props.fooBarBaz(email, password, signInUser);
This allowed me to use signInUser outside of the component just as I did within it.
So in your case it should be as simple as keeping:
export default connect(
null,
{ signInUser },
)(SignInScreen)
and calling Login like:
Login(email, password, signInUser);
I am using redux-saga along with reactjs. I am using mapDispatchToProps to trigger onClick changes with values but I am getting above error saying that dispatch is not defined anyone please let me know how to resolve this in saga way?
import { connect } from 'react-redux';
import { updateModifiedValue } from "../actions/programActions";
import { bindActionCreators } from 'redux';
export class ProgramProfileContainer extends React.Component {
render() {
return (
<div>
<ProgramVolumeComponent
updateModifiedGrowth = {(value) => updateModifiedValue(value,this.props.match.params.program_id)}
/>
</div>
)
}
}
const mapStateToProps = (state) => {
console.log("update state", state)
return {
programProfileData: state.programDetailReducer.programDetails,
}
}
const mapDispatchToProps= (dispatch) => (
bindActionCreators({updateModifiedValue},dispatch)
)
export default connect(
mapStateToProps,
mapDispatchToProps)(ProgramProfileContainer)
this is my action
export function updateModifiedValue(Value,Id){
console.log("mval",Value)
console.log("id",Id)
return {
type:types.MODIFIED_GROWTH,
growthValue
}
}
here is my index saga
export default function* startForman() {
console.log("index saga")
yield fork(watcher);
}
watcher
export default function* watcher(){
yield takeLatest(types.LISTS,myCallSaaga)
}
and my calll saaga
export default function* myCallSaaga({Value,Id}){
const array=[Value,Id]
try {
const Data = yield call(growthdetail,...array)
yield [
put({ type: types.MODIFIED, Detail: Data })
]
} catch (error) {
yield put({
type: 'FETCH_ERROR',
error
});
}
}
and my reducer
export default function(state=[],action){
switch(action.type){
case types.PRO_LIST:
return [...state,action.List]
case types.MODIFIED:
return {...state,growth:4}
default:
return state
}
}
I think the error is that you are calling the action directly from your import and not from your props, which is what mapDispatchToProps is for. Try this:
import programActionsCreator from "../actions/programActions";
...
render() {
const { updateModifiedValue } = this.props.actions;
return() {
...
updateModifiedGrowth = {(value) => updateModifiedValue(value, this.props.match.params.program_id)}
...
}
...
const mapDispatchToProps= (dispatch) => ({
actions: bindActionCreators(programActionsCreator, dispatch)
})
from rowland's comment and from this github post I made the changes like this
const mapDispatchToProps= (dispatch) => {
return { dispatch,
...bindActionCreators({
updateModifiedValue
}, dispatch)}//bindActionCreators({updateModifiedValue},dispatch)
}
and
<ProgramVolumeComponent
updateModifiedGrowth = {(value) => this.props.updateModifiedValue(value,this.props.match.params.program_id)}
/>
basically we need to pass our own dispatch we are mapDispatchToProps