2
votes

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?

3
Judging by your use of this.setState() this is a class-based component. You cannot use React hooks (like useDispatch()) in a class-based component, you have to use connect() instead to have the dispatch function injected into this.props (using mapDispatchToProps as in the duplicate I flagged is an optional alternative)rickdenhaan

3 Answers

1
votes

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;
    }
}

}

0
votes

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.

0
votes

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());
        }
    }
    ...
}