Action
export const VERIFY = () => dispatch => {
dispatch({type: "VERIFY"})
};
Reducer
const signedReducer = (state=user, action) => {
console.log(action);
switch(action.type){
case "VERIFY": {
return {...state, email: "example#gmail.com"};
}
default: {
return state;
}
}
}
_app.js code
import { wrapper } from '../redux/store';
function MyApp({ Component, pageProps }) {
return <>
<Component {...pageProps}/>
</>
}
MyApp.getInitialProps = async(appContext) => {
let { pageProps } = appContext
pageProps = {};
if(appContext.Component.getInitialProps){
pageProps = await appContext.Component.getInitialProps(appContext.ctx);
}
return {
pageProps,
};
};
export default wrapper.withRedux(MyApp);
& finally pages/home.js
import { useEffect } from "react";
import PrivateLayout from "../components/PrivateLayout/PrivateLayout";
import { connect } from "react-redux";
import { VERIFY } from "../redux/actions/signActions";
function Home() {
// console.log(user);
// useEffect(() => {
// }, [user]);
return (
<div >
{ true ?
<h1>Logged In</h1>
:
<h1>Please login again</h1>
}
</div>
)
}
const mapStateToProps = state => ({
user: state
})
const mapDispatchToProps = {
VERIFY: VERIFY
}
export default connect(mapStateToProps, mapDispatchToProps)(Home);
Please check, I've put an console.log statement in the reducer.
Whenever I run the code the console.log statement display these action type only
##redux/INIT6.z.d.a.h.7
##redux/PROBE_UNKNOWN_ACTIONq.x.h.3.5.d
But never takes the action VERIFY.
Looked across the internet but haven't found any solution regarding this. Why?
This should solve your problem:
Also you need to call VERIFY in your component.
Action:
export const VERIFY = () => ({type: "VERIFY"});
reference: https://react-redux.js.org/using-react-redux/connect-mapdispatch
Related
First of all I rarely use functional component, but this time I required to use it. So, I have this component called Login that use redux :
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { getLoginData } from "../../redux/actions/LoginActions";
function Login() {
useEffect(() => {
const { getLoginData } = this.props;
getLoginData("test");
}, []);
return (
<div>
<h1>Login</h1>
</div>
);
}
const mapStateToProps = (state) => ({
login: state.login,
});
const mapDispatchToProps = (dispatch) => ({
getLoginData: (value) => dispatch(getLoginData(value)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Login);
It produce error since this is undefined. But, if I change it to class component like this:
import React from "react";
import { connect } from "react-redux";
import { getLoginData } from "../../redux/actions/LoginActions";
class Login extends React.Component {
componentDidMount() {
const { getLoginData } = this.props;
getLoginData("test");
}
render() {
return (
<div>
<h1>Login</h1>
</div>
);
}
}
const mapStateToProps = (state) => ({
login: state.login,
});
const mapDispatchToProps = (dispatch) => ({
getLoginData: (value) => dispatch(getLoginData(value)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Login);
It will worked as expected(the redux is also worked). The question is, How can I pass this.props to functional component?
Function components get their props passed in as the argument to that function:
function Login(props) {
useEffect(() => {
props.getLoginData("test");
}, []);
// ...
}
// Or with destructuring:
function Login({ login, getLoginData }) {
useEffect(() => {
getLoginData("test");
}, []);
// ...
}
That said, if you're using a function component, then it's simpler to use hooks instead of connect:
function Login() {
const login = useSelector(state => state.login);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getLoginData("test"));
}, []);
//...
}
// Note that there is no mapStateToProps/mapDispatchToProps/connect here
export default Login;
As per the React docs, you pass a props object to the function and access the values as attributes of props.
So, for your implementation, you'd do it like this:
function Login(props) {
useEffect(() => {
props.getLoginData("test");
}, []);
return (
<div>
<h1>Login</h1>
</div>
);
}
Or, you could replace function Login(props) with function Login({getLoginData}) to unwrap the value and replace props.getLoginData("test") with getLoginData("test").
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.
In my react app, I have a withAuth HOC which checks if the user is authenticated before the wrapped component is loaded. It looks up the redux store to check auth status and loads the component, if isAuth is true. However, I can't access redux store from the HOC. when I try, I get the following error message on the browser. Any help to overcome this problem is highly appreciated.
withAuth.js
import React, { useState, useEffect } from 'react';
import { setAuth } from '../actions/Actions';
import { connect } from 'react-redux';
function withAuth(WrappedComponent) {
return (props) => {
const [isAuth, setAuth] = useState(false);
useEffect(() => {
if (props.isAuth) {
setAuth(true);
} else {
props.history.push('/catalog');
}
}, [props.history]);
return isAuth ? <WrappedComponent {...props} /> : <p>Loading..</p>
};
}
const mapStateToProps = (state) => {
return {
isAuth: state.isAuth,
};
};
const mapDispatchToProps = (dispatch) => {
return {
setAuth: (status) => dispatch(setAuth(status)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(withAuth);
You cannot pass a HOC to connect, you have to pass a function component:
export default function withAuth(WrappedComponent) {
const Component = (props) => {
const [isAuth, setAuth] = useState(false);
useEffect(() => {
if (props.isAuth) {
setAuth(true);
} else {
props.history.push('/catalog');
}
}, [props.history, props.isAuth]);//forgot dependency here
return isAuth ? (
<WrappedComponent {...props} />
) : (
<p>Loading..</p>
);
};
const mapStateToProps = (state) => {
return {
isAuth: state.isAuth,
};
};
const mapDispatchToProps = (dispatch) => {
return {
setAuth: (status) => dispatch(setAuth(status)),
};
};
return connect(
mapStateToProps,
mapDispatchToProps
)(Component);
}
I try to create a Redux and I have a problem when I try to do dispatch is not working.
Action file, userActions.js:
export const setId = () => {
console.log("Enter to set id func");
return {
type: 'SET_ID'
}
}
Reducer file, userReducer.js:
const INITIAL_STATE = {
id: "",
email: "",
name: "",
};
const userReducer = (state = INITIAL_STATE, action) => {
console.log('Enter to userReducer');
switch (action.type) {
case "SET_ID": {
// console.log(action.payload);
}
default: {
return state;
}
}
}
export default userReducer;
combineReducers file:
import userReducer from "./userReducer";
import { combineReducers } from "redux";
const allReducers = combineReducers({
userReducer: userReducer
})
export default allReducers;
App.js file:
import React from 'react';
import Routes from "./Routes";
import { createStore } from "redux";
import allReducer from "./app/reducers";
import { Provider } from "react-redux";
const store = createStore(
allReducer
);
const App = () => {
return (
<Provider store={store}>
<Routes />
</Provider>
);
};
export default App;
In login screen file, I have button when I click on him call to dispatch to "setId" action.
Here some of my code from Login.js:
import { useDispatch } from 'react-redux';
import { setId } from '../actions/userActions';
handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
this.setState({ generalError: error });
} else {
const dispatch = useDispatch();
console.log('uid: ', user.user.uid);
dispatch(setId());
alert("Login!");
}
}
What is the problem and why is not enter to setId action?
You can try with like this
const userReducer = (state = INITIAL_STATE, action) =>dispatch =>{
console.log('Enter to userReducer');
switch (action.type) {
case "SET_ID": {
// console.log(action.payload);
}
default: {
return state;
}
}
}
I didn't quite understand your question, but I'll give you an example of an action of mine
export const register_user = ({ name, email, password, password_confirmation }) => {
return dispatch => {
dispatch(
{
type: CREATE_USER
}
)
let url = "/users"
Axios.post(`${SERVER}${url}`, {
"user": {
"name": name,
"email": email,
"password": password,
"password_confirmation": password_confirmation
}
})
.then(() => {
Alert.alert('Registrado com sucesso!')
registerUserSuccess(dispatch)
})
.catch((err) => {
registerUserError(err, dispatch)
})
}
}
const registerUserSuccess = (dispatch) => {
dispatch(
{
type: CREATE_USER_SUCCESS
}
)
this.props.navigation.navigate('Login')
}
const registerUserError = (err, dispatch) => {
dispatch(
{
type: CREATE_USER_ERROR
}
)
Alert.alert('Algo deu errado, verifique suas credenciais.')
}
The type is exported from my reducer.
And the register_user constant is imported and used on my register screen.
Hooks cannot be used inside a function. They need to declared directly inside the functional component.
Also useDispatch hook cannot be used inside a class component, you must use connect for a class component.
Assuming you have a class component, judging by how you use this.setState, you would write your code like
class Login extends React.Component {
...
handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
this.setState({ generalError: error });
} else {
const dispatch = this.props;
console.log('uid: ', user.user.uid);
dispatch(setId());
alert("Login!");
}
}
...
}
export default connect()(Login)
If however you were to write login as a functional component, you would write it like
const Login = (props) => {
const dispatch = useDispatch();
const [state, setState] = useState({});
...
const handleLoginResult = (error, user) => {
console.log('Enter to handleLoginResult');
if (error !== "") {
setState({ generalError: error });
} else {
console.log('uid: ', user.user.uid);
dispatch(setId());
}
}
...
}
I created an action creator that is simply supposed to make a get request to my API and return with a list of all projects. However, for some reason, my return dispatch in my thunk function is not firing at all. It gets to the console.log() statement and just ends. There are no consoles errors, and no network calls being made either as far as I can tell. Any ideas why it would do absolutely nothing?
Dashboard.js (component)
import ProjectItem from "../Project/ProjectItem";
import styles from "./Dashboard.module.css";
import CreateProjectButton from "../CreateProjectButton/CreateProjectButton";
import { connect } from "react-redux";
import { getProjects } from "../../Redux/getProjects/actions";
const Dashboard = props => {
useEffect(() => {
console.log("blah");
getProjects();
}, []);
return (
<div className={styles.dashboardContainer}>
<h1>Projects</h1>
<br />
<CreateProjectButton />
<br />
<hr />
<ProjectItem />
</div>
);
};
const mapStateToProps = state => {
return {
projects: state
};
};
const mapDispatchToProps = dispatch => {
return {
getProjects: () => dispatch(getProjects())
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
action.js (action creator)
import { GET_PROJECTS_SUCCESS, GET_PROJECTS_ERROR } from "./constants";
export const getProjectsSuccess = payload => {
console.log("getProjectSuccess", payload);
return {
type: GET_PROJECTS_SUCCESS,
payload
};
};
export const getProjectsError = () => {
console.log("there was an error");
return {
type: GET_PROJECTS_ERROR
};
};
export function getProjects() {
console.log("getProject");
return dispatch => {
axios
.get("/project/all")
.then(res => dispatch(getProjectsSuccess(res.data)))
.catch(err => dispatch(getProjectsError(err)));
};
}
index.js (getProject reducer)
const initialState = {
projects: [], //array of projects
project: {}, // single project for update case
reRender: false
};
const getProjectsReducer = (state = initialState, action) => {
switch (action.type) {
case GET_PROJECTS_SUCCESS:
return { ...state, projects: action.payload }; // will need to change action.payload later on
default:
return state;
}
};
export default getProjectsReducer;
constants.js
export const GET_PROJECTS_SUCCESS = "GET_PROJECTS_SUCCESS";
export const GET_PROJECTS_ERROR = "GET_PROJECTS_ERROR";
rootReducer.js
import createProjectReducer from "./createProject/index";
import getProjectsReducer from "./getProjects/index";
const rootReducer = (state = {}, action) => {
return {
project: createProjectReducer(state.project, action),
projects: getProjectsReducer(state.projects, action)
};
};
export default rootReducer;
FIXED: After reading up on the use effect hook in functional components I realized I was missing props.getProjects in the useEffect function in dashboard.js!