Access Dispatch inside of Function - reactjs

I want my function below, "VerifyEmailResend" to have access to the two dispatch methods inside of mapDispatchToProps. How do I do that?
VerifyEmailResend() is exported because i want it available to be called throughout my application.
This app is written in React using Redux.
I know normally the connect method is used, but connect is for react components specifically. Is there something similar here I am missing?
import React, { Component, Fragment } from 'react'
import { api } from '../../api'
import { bool, func } from 'prop-types'
import VerifyEmailResent from './VerifyEmailResent'
import VerifyEmailVerified from './VerifyEmailVerified'
import { connect } from 'react-redux'
class VerifyEmail extends Component {
static propTypes = {
// has the verify email been resent \\
verifyEmailResent: bool,
// have you already verified your email \\
verifyEmailVerified: bool,
// set status of verify email \\
onSetVerifyEmailResent: func.isRequired,
// set status of the email verified \\
onSetVerifyEmailVerified: func.isRequired
}
resent = () => {
const { onSetVerifyEmailResent } = this.props
onSetVerifyEmailResent(false)
}
verified = () => {
const { onSetVerifyEmailVerified } = this.props
onSetVerifyEmailVerified(false)
}
render() {
const { verifyEmailResent, verifyEmailVerified } = this.props
return (
<Fragment>
{verifyEmailResent && (
<VerifyEmailResent action={this.resent} />
)}
{verifyEmailVerified && (
<VerifyEmailVerified action={this.verified} />
)}
</Fragment>
)
}
}
const mapStateToProps = state => ({
verifyEmailResent: state.eventListenerState.verifyEmailResent,
verifyEmailVerified: state.eventListenerState.verifyEmailResent
})
const mapDispatchToProps = dispatch => ({
onSetVerifyEmailResent: verifyEmailResent =>
dispatch({ type: 'VERIFY_EMAIL_RESENT_SET', verifyEmailResent }),
onSetVerifyEmailVerified: verifyEmailVerified =>
dispatch({ type: 'VERIFY_EMAIL_RESENT_VERIFIED', verifyEmailVerified })
})
const VerifyEmailResend = () => () => {
api.user.resendEmailVerification().then(data => {
if (data.resent) {
//onSetVerifyEmailResent(true)
}
if (data.verified) {
//onSetVerifyEmailVerified(false)
}
})
}
export connect(null, mapDispatchToProps)(VerifyEmailResend)
export default connect(
mapStateToProps,
mapDispatchToProps
)(VerifyEmail)

I am not sure what you're confused at. But you can do it:
const VerifyEmailResend = () => {}
export default connect(null, mapDispatchToProps)(VerifyEmailResend)
As per you need a named export, you can do it like:
export {
VerifyEmailResend: connect(null, mapDispatchToProps)(VerifyEmailResend)
}
And you can import it normally like:
import { VerifyEmailResend } from '..'
And as per your comment, you can call it like followings depending your need of field:
{ VerifyEmailResend() }
Or like:
<VerifyEmailResend />

Related

React redux not fetching data from API

Hi im new to redux and im trying to create a movie app using the API from www.themoviedb.org. I am trying to display the popular movies and im sure the API link works since ive tested it in postman but i cant seem to figure out why redux doesnt pick up the data.
//action
import { FETCH_POPULAR } from "./types";
import axios from "axios";
export const fetchPopularMovies = () => (dispatch) => {
axios
.get(
`https://api.themoviedb.org/3/movie/popular?api_key=${API}&language=en-US`
)
.then((response) =>
dispatch({
type: FETCH_POPULAR,
payload: response.data
})
)
.catch((err) => console.log(err));
};
//reducer
import { FETCH_POPULAR } from "../actions/types";
const initialState = {
popular: [],
};
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_POPULAR:
return {
...state,
popular: action.payload,
};
default:
return state;
}
}
import React from "react";
import { connect } from "react-redux";
import Popular from "./Popular";
const FetchedPopular = (props) => {
const { popular } = props;
let content = "";
content =
popular.length > 0
? popular.map((item, index) => (
<Popular key={index} popular={item} />
))
: null;
return <div className="fetched-movies">{content}</div>;
};
const mapStateToProps = (state) => ({
popular: state.popular.popular,
});
export default connect(mapStateToProps)(FetchedPopular);
import React from "react";
import "../Styles.css";
const Popular = (props) => {
return (
<div className="movie-container">
<img
className="poster"
src={`https://image.tmdb.org/t/p/w400/${props.poster_path}`}
/>
</div>
);
};
export default Popular;
I cant really tell what I'm missing can someone help?
Next to mapStateToProps you need to create mapDispatchToProps. After that, you will be able to call your Redux action from your React component.
I suggest you the mapDispatchToProps as an Object form. Then you need to use this mapDispatchToProps as the second parameter of your connect method.
When you will have your action mapped to your component, you need to call it somewhere. It is recommended to do it for example on a component mount. As your React components are Functional components, you need to do it in React useEffect hook.
import React, { useEffect } from "react";
import { connect } from "react-redux";
import Popular from "./Popular";
import { fetchPopularMovies } from 'path_to_your_actions_file'
const FetchedPopular = (props) => {
const { popular } = props;
let content = "";
useEffect(()=> {
// call your mapped action (here it is called once on component mount due the empty dependency array of useEffect hook)
props.fetchPopularMovies();
}, [])
content =
popular.length > 0
? popular.map((item, index) => (
<Popular key={index} popular={item} />
))
: null;
return <div className="fetched-movies">{content}</div>;
};
const mapStateToProps = (state) => ({
popular: state.popular.popular,
});
// create mapDispatchToProps
const mapDispatchToProps = {
fetchPopularMovies
}
// use mapDispatchToProps as the second parameter of your `connect` method.
export default connect(mapStateToProps, mapDispatchToProps)(FetchedPopular);
Moreover, as I wrote above in my comment, your Popular does not have the prop poster_path but it has the prop popular which probably has the property poster_path.
import React from "react";
import "../Styles.css";
const Popular = (props) => {
return (
<div className="movie-container">
<img
className="poster"
src={`https://image.tmdb.org/t/p/w400/${props.popular.poster_path}`}
/>
</div>
);
};
export default Popular;

this.props.dispatch is not a function. Not able to dispatch mapdispatchtoprops

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.

Why can't I call this.state in my redux reducer?

I made a reducer that fetches admins, and I want it to display certain admins when I call it in my reducer but I am getting Undefined.
I am still very new to redux so apologies for my mistakes.
I tried to include all the relevant folders:
App.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../store/actions';
class App extends Component {
async componentDidMount() {
fetch(constants.adminUrl + '/admins/data', {
method: 'GET'
}).then((res) => {
return res.json()
}).then(async (res) => {
this.props.setAdminsInColumns(res.admins)
}).catch((error) => {
toast.error(error.message)
})
}
render() {
return (
{/* SOME CODE */}
);
}
}
let app = connect(null, actions)(App);
export default app;
columnsReducer.js
import { FETCH_ADMINS } from '../actions/types'
import { Link } from 'react-router-dom'
import constants from '../../static/global/index'
import React from 'react';
import { toast } from 'react-toastify'
const initialState = {
admins: [],
{
Header: "Responsible",
accessor: "responsibleAdmin",
style: { textAlign: "center" },
// Place where I want to fetch certain admins and get undefined
Cell: props => <span>{props.value && this.state.admins.name ? this.state.admins.find(admin => admin.id === props.value).name : props.value}</span>
}
}
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_ADMINS:
return { ...state, admins: action.admins}
default:
return state
}
}
index.js
import { FETCH_ADMINS } from "./types"
/**
* starts loader for setting admin
*/
export const setAdminsInColumns = (admins) => async dispatch => {
dispatch({ type: FETCH_ADMINS, admins })
}
types.js
export const FETCH_ADMINS = 'fetch_admins'
When I console.log(action.admins) inside the switch case FETCH_ADMINS in the columnsReducer.js file, I can see all the admin information I want, is there a way to make the state global in the columnsReducer.js file so I can read it?
Any help is appreciated!
use mapStateToProps in the connect method. like below
let mapStateToProps = (state)=>{
return {
admins :[yourcolumnsReducer].admins
}
}
let app = connect(mapStateToProps, actions)(App);
//you can use this.props.admins inside your component
MapStateToProps reference

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.)

How to access state from a helper module in React?

I'm creating a module named isMember. This module should be able to check if state.current_user.member is true or not.
1 import { select } from "redux-saga/effects"
2
3 export function* isMember() {
4 const { member } = yield select((state: any) => state.current_user)
5 console.log("isMember: ", member)
6 return member
7 }
I'm trying to test it like this in my view:
import { isMember } from "../utils/isMember"
return (
{ isMember() && <span> is a member </span> }
)
But that yields this error:
select is an Effect object of redux-saga. It is a tool to handle redux's side effects and should be used exclusively in a saga.
Generally, to test your module, you need to put it in a saga watcher that watches over an action:
import { takeEvery } from 'redux-saga'
function* watchTestingAction() {
yield takeEvery(TESTING_ACTION_TYPE, isMember)
}
and dispatch that action in React component:
import { connect } from 'react-redux'
...
return (
<MainContainer withScroll>
<GjeButton
title="isMember?"
onPress={this.props.testingAction} />
...
const mapState = (state) => ({})
const mapDispatch = (dispatch) => ({
testingAction: () => dispatch({ type: TESTING_ACTION_TYPE })
})
export default connect(mapState, mapDispatch)(YourComponent)
EDIT: To get state data, redux-saga is not needed. What you need is connect from react-redux.
import React, { Component } from 'react'
import { connect } from 'react-redux'
...
class MyComponent extends Component
render() {
return (
<MainContainer withScroll>
<GjeButton
title="isMember?"
onPress={() => { console.log(this.props.isMember) }} />
)
}
}
const mapState = (state) => ({
isMember: state.current_user.member || false
})
export default connect(mapState)(YourComponent)

Resources