I'm trying to create an alert component, however for this I need to add an item (from anywhere) to the list of alerts in the state.
I have this code:
alertReducer.js:
import { SET_ALERT, GET_ALERTS, SET_ALERT_SHOWED } from "../actions/types";
const initialState = {
alerts: [
{
id: 0,
title: "teste",
message: "teste",
isShowed: false,
type: "success"
}
]
};
export default function(state = initialState, action) {
switch (action.type) {
case SET_ALERT:
return { ...state, alert: action.payload };
case SET_ALERT_SHOWED:
return {
...state,
alert: state.alerts.map(a =>
a.id === a.payload.id ? (a = action.payload) : a
)
};
case GET_ALERTS:
return { ...state };
default:
return state;
}
}
alertActions.js
import { SET_ALERT, GET_ALERTS, SET_ALERT_SHOWED } from "./types";
import axios from "axios";
export const getAlerts = () => dispatch => {
dispatch({
type: GET_ALERTS,
payload: null
});
};
export const setAlertShowed = alert => dispatch => {
dispatch({
type: SET_ALERT_SHOWED,
payload: null
});
};
export const setAlert = alert => dispatch => {
console.log("set alert:");
this.setState(state => {
state.alert.alerts.push(alert);
return null;
});
dispatch({
type: SET_ALERT,
payload: null
});
};
alerts.js (component)
import React from "react";
import { Link } from "react-router-dom";
import { Modal, ModalHeader, ModalBody, ModalFooter } from "reactstrap";
import {
Panel,
PanelHeader,
PanelBody
} from "./../../components/panel/panel.jsx";
import SweetAlert from "react-bootstrap-sweetalert";
import ReactNotification from "react-notifications-component";
import "react-notifications-component/dist/theme.css";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { getAlerts, setAlertShowed } from "../../actions/alertActions";
class Alerts extends React.Component {
constructor(props) {
super(props);
this.addNotification = this.addNotification.bind(this);
this.notificationDOMRef = React.createRef();
}
componentWillReceiveProps(nextProps) {
console.log("atualizou alertas");
console.log(this.props);
console.log(nextProps);
}
componentDidMount() {
this.props.getAlerts();
this.showAlerts();
}
showAlerts() {
const { alerts } = this.props;
alerts
.filter(a => !a.isShowed)
.map((a, i) => {
this.addNotification.call(this, a);
a.isShowed = true;
setAlertShowed(a);
});
}
addNotification(alert) {
this.notificationDOMRef.current.addNotification({
title: alert.title,
message: alert.message,
type: alert.type,
insert: "top",
container: "top-right",
animationIn: ["animated", "fadeIn"],
animationOut: ["animated", "fadeOut"],
dismiss: { duration: 2000 },
dismissable: { click: true }
});
}
render() {
const { alerts } = this.props;
return <ReactNotification ref={this.notificationDOMRef} />;
}
}
Alerts.propTypes = {
alerts: PropTypes.array.isRequired,
getAlerts: PropTypes.func.isRequired,
setAlertShowed: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
alerts: state.alert.alerts
});
export default connect(
mapStateToProps,
{ getAlerts, setAlertShowed }
)(Alerts);
So I have this helper I'm trying to do, it would serve so that from anywhere in the application I can trigger addAlert and generate a new alert, but I have no idea how to call the setAlert function inside the alertActions.js, what I was able to do is call the SET_ALERT through the store.dispatch, but apparently this is not triggering the setAlert or I am doing something wrong
import uuid from "uuid";
import { createStore } from "redux";
import { setAlert } from "../actions/alertActions";
import { SET_ALERT } from "../actions/types";
import alertReducer from "../reducers/alertReducer";
export function addAlert(state, title, message, type = "success") {
// const store = createStore(alertReducer);
// const state = store.getState();
const newalert = {
id: uuid.v4(),
title,
message,
isShowed: false,
type: type
};
console.log("state");
console.log(state);
// this.setState(state => {
// state.alert.alerts.push(alert);
// return null;
// });
// store.dispatch({
// type: SET_ALERT,
// payload: newalert
// });
// store.dispatch(setAlert(newalert));
// store.dispatch(SET_ALERT);
// this.setState(prevState => ({
// alert.alerts: [...prevState.alert.alerts, newalert]
// }))
}
PS. My react knowledge is very low yet and English it's not my primary language, if I don't make myself clear please ask anything.
Thank you.
Do like this:
// Create alert which you want to show
const alerts = [
{
id: 0,
title: "teste",
message: "teste",
isShowed: false,
type: "success"
}];
componentDidMount() {
this.props.getAlerts();
this.showAlerts();
// this will call alerts action
this.props.callAlert(alerts );
}
const mapDispatchToProps = dispatch=> ({
callAlert: (alert) => dispatch(setAlert(alert)),
});
export default connect(
mapStateToProps,
mapDispatchToProps,
{ getAlerts, setAlertShowed }
)(Alerts);
Finally! I created the store by adding compose and applyMiddleware, I still have to study how this works best but it worked.
The helper code to add alert looks like this:
import uuid from "uuid";
import { createStore, dispatch, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { setAlert } from "../actions/alertActions";
import alertReducer from "../reducers/alertReducer";
export function addAlert(title, message, type = "success") {
const store = createStore(alertReducer, compose(applyMiddleware(thunk)));
const newalert = {
id: uuid.v4(),
title,
message,
isShowed: false,
type: type
};
store.dispatch(setAlert(newalert));
}
Related
How can I add a charging indicator based on the Redux status?
I need to place a loading screen while sending the data.
charging indicator component
import React from 'react';
import { StyleSheet } from 'react-native';
import AnimatedLoader from "react-native-animated-loader";
import {connect} from 'react-redux'
class Loader extends React.Component {
constructor(props) {
super(props);
this.state = {visible: false };
}
// componentDidMount() {
// setInterval(() => {
// this.setState({
// visible: !this.state.visible
// });
// }, 2000);
// }
render() {
const { visible } = this.props;
if (!visible) return outVisible();
return (
<AnimatedLoader
visible={visible}
overlayColor="rgba(255,255,255,0.75)"
source={require("./loader.json")}
animationStyle={styles.lottie}
speed={1}
>
<Text>Carregando...</Text>
</AnimatedLoader>
);
}
}
const styles = StyleSheet.create({
lottie: {
width: 200,
height: 200
}
});
const mapStateToProps = (state) => ({visible: state.visible});
const mapDispatchToProps = dispatch => {
return {outVisible: () => dispatch(setVisible({visible: false}))}
}
export default connect(mapStateToProps,mapDispatchToProps)(Loader)
Action
import { SET_VISIBLE } from './actionsTypes'
export const setVisible = visible => {
return {
type: SET_VISIBLE,
payload: visible
}
}
Reducer
import { SET_VISIBLE } from '../actions/actionsTypes'
const initialState = {
visible: false
}
const reducer = (state = initialState, action) => {
switch(action.type) {
case SET_VISIBLE:
return {
...state,
visible: action.payload.visible
};
default:
return state;
}
}
export default reducer
Store Config
import {
createStore,
combineReducers,
compose,
applyMiddleware
} from 'redux'
import thunk from 'redux-thunk'
import postReducer from './reducers/post'
import userReducer from './reducers/user'
import messageReducer from './reducers/message'
import loadingReducer from './reducers/loading'
const reducers = combineReducers({
user: userReducer,
post: postReducer,
message: messageReducer,
visible: loadingReducer
})
const storeConfig = () => {
return createStore(reducers, compose(applyMiddleware(thunk)))
}
export default storeConfig
actions types
export const USER_LOGGED_IN = 'USER_LOGGED_IN'
export const USER_LOGGED_OUT = 'USER_LOGGED_OUT'
export const SET_MESSAGE = 'SET_MESSAGE'
export const LOADING_USER = 'LOADING_USER'
export const USER_LOADED = 'USER_LOADED'
export const CREATING_POST = 'CREATING_POST'
export const POST_CREATED = 'POST_CREATED'
export const SET_POSTS = 'SET_POSTS'
export const SET_VISIBLE = 'SET_VISIBLE'
app.js
import React, { Component } from 'react'
import { Alert } from 'react-native'
import { connect } from 'react-redux'
import Routes from "./routes";
import { setMessage } from './store/actions/message'
class App extends Component {
componentDidUpdate = () => {
if(this.props.text && this.props.text.toString().trim())
{
Alert.alert(this.props.title || 'Mensagem',this.props.text.toString())
this.props.clearMessage()
}
}
render() {
return (
<Routes />
)
}
}
const mapStateToProps = ({ message}) => {
return {
title: message.title,
text: message.text,
}
}
const mapDispatchToProps = dispatch => {
return {
clearMessage: () => dispatch(setMessage({ title: '', text: '' }))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
Right after the data is sent to the API, I need to return a load indicator to the user, until that data is stored.
I am getting a dispatch is not defined error from 'shopfront' code. I believe it is because i'm not passing the properties down to the next level but I'm not sure if that is correct or not. I want to be able to pass the dispatch function through to the product.actions code correctly.
I have tried to narrow down the problem as much as possible by removing unnecessary code. I have a user reducer that is working correctly but I don't know why this product reducer isn't
// products.reducer
const initialState = {
products: null,
error: null
};
const ProductReducer = (state = initialState, action) => {
let newState = null;
switch(action.type){
case "GET_ALL_PRODUCTS": newState = {
...state,
products: action.products
};
return newState;
case "GET_ALL_PRODUCTS_FAIL": newState = {
...state,
error: action.error
};
return newState;
default: return state;
}
};
export default ProductReducer;
// index
import React from "react";
import ReactDOM from "react-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import { register } from "./serviceWorker";
import { createStore, combineReducers, applyMiddleware, compose } from "redux";
import { Provider } from "react-redux";
import thunk from "redux-thunk";
import UserReducer from "./store/reducers/users.reducers";
import ProductReducer from "./store/reducers/products.reducer";
import "./index.css";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
const appReducer = combineReducers({
usersRed: UserReducer,
productsRed: ProductReducer
});
const logger = (store) => {
return next => {
return action => {
console.log("Middleware dispatching ");
console.log(action);
const result = next(action);
console.log("Middleware next state ");
console.log(store.getState());
return result;
};
};
};
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const appStore = createStore(appReducer, composeEnhancers(applyMiddleware(logger, thunk)));
const app = (
<BrowserRouter>
<Provider store={appStore}>
<App />
</Provider>
</BrowserRouter>
);
ReactDOM.render(app, document.getElementById("root"));
register();
// shopfront
import React, { Component } from "react";
import { Container, Row, Col, InputGroup, InputGroupAddon, Button } from "reactstrap";
import { withRouter } from "react-router-dom";
import { connect } from "react-redux";
import { Alert } from "reactstrap";
import * as actionMethods from "../../store/actions/index.actions";
import Product from "../../components/Product/Product";
class Shopfront extends Component {
state = {
onAlert: false,
internalError: null
};
componentDidMount() {
this.props.loadAllProducts(5);
console.log("component_did_mount_run")
}
render() {
let ProductsList = <h1>No Products Yet!</h1>;
if (this.props.products !== null) {
ProductsList = this.props.products.map(Product => {
return <Product
key={Product.id}
title={Product.name}
excerpt={Product.description}
medialink={Product.permalink}
ProductId={Product.id}
/>;
});
}
return (
<Container>
{ProductsList}
</Container>
);
}
};
const mapStateToProps = (state) => {
return {
products: state.productsRed.products,
error: state.productsRed.error
};
};
const mapDispatchToProps = (dispatch) => {
return {
loadAllProducts: (perpage) => { dispatch(actionMethods.loadAllProducts(perpage)) }
};
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Shopfront));
// index.actions
export {
loadAllProducts
} from "./product.actions";
// product.actions
import wcapi from "../../axios-wp";
export const loadAllProducts = (perpage) => {
wcapi.get("products", {
per_page: perpage,
})
.then((response) => {
// Successful request
let productsRes = response.data;
dispatch({ type: "GET_ALL_PRODUCTS", products: productsRes });
})
.catch((err) => {
// Invalid request, for 4xx and 5xx statuses
dispatch({ type: "GET_ALL_PRODUCTS_FAIL", error: err });
})
}
Thank you for your help!
it is because you are not returning dispatch from your loadAllProducts action
/ product.actions
import wcapi from "../../axios-wp";
export const loadAllProducts = (perpage) => (dispatch) => { //make this change
wcapi.get("products", {
per_page: perpage,
})
.then((response) => {
// Successful request
let productsRes = response.data;
dispatch({ type: "GET_ALL_PRODUCTS", products: productsRes });
})
.catch((err) => {
// Invalid request, for 4xx and 5xx statuses
dispatch({ type: "GET_ALL_PRODUCTS_FAIL", error: err });
})
}
I have ever faced such this issue before. Then I used return dispatch => {} like this:
export const loadAllProducts = perpage => {
return dispatch => {
wcapi.get("products", {
per_page: perpage,
})
.then((response) => {
// Successful request
let productsRes = response.data;
dispatch({ type: "GET_ALL_PRODUCTS", products: productsRes });
})
.catch((err) => {
// Invalid request, for 4xx and 5xx statuses
dispatch({ type: "GET_ALL_PRODUCTS_FAIL", error: err });
})
}
}
I'm trying to migrate our codebase to use react-navigation: 3.11 from v1 and having issues. I created a small gist here to run through the issue and provided codebase.
I am using react-navigation-redux-helpers with the new react-navigation to use the createReduxContainer function in other to maintain my previous redux setup.
I'm getting this error - Cannot read property 'routes' of undefined
https://gist.github.com/bwoodlt/773c62d4ba3dbe0cea150a9d956bec3f
// #flow
// root navigator
import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import TabNavigation from './TabNavigation';
import FCLaunch from '../../Components/FCLaunch';
import { FCLAUNCH } from '../constants';
import { HeaderText } from '../Components';
import * as actionsOnboarding from '../../Screens/Onboarding/actions';
import StagingArea from '../StagingArea';
const RouteConfigs = {
StagingArea: {
screen: StagingArea,
defaultNavigationOptions: {
header: null
}
},
[FCLAUNCH]: {
screen: FCLaunch,
navigationOption: () => ({
header: null
})
}
};
const StackNavigatorConfig = {
initialRouteName: 'StagingArea',
mode: Platform.OS === 'ios' ? 'modal' : 'card'
};
export default createAppContainer(
createStackNavigator(RouteConfigs, StackNavigatorConfig)
);
// #flow
// AppWithNavigationState
import * as React from 'react';
import codePush from 'react-native-code-push';
import OneSignal from 'react-native-onesignal';
import { connect } from 'react-redux';
import DeviceInfo from 'react-native-device-info';
import PropTypes from 'prop-types';
import {
createReactNavigationReduxMiddleware,
createReduxContainer
} from 'react-navigation-redux-helpers';
import { createAppContainer } from 'react-navigation';
import { AppNavigation } from './Navigation';
import { Storage } from '../Utils';
import { NAME } from './constants';
import type { Dispatch } from '../Model';
type IAppWithNavigationProps = {
dispatch: Dispatch
};
const codePushOptions = {
checkFrequency: codePush.CheckFrequency.ON_APP_RESUME
};
const middleware = createReactNavigationReduxMiddleware(state => state[NAME]);
class AppWithNavigationStateObject extends React.PureComponent<
{},
IAppWithNavigationProps
> {
async componentDidMount() {
codePush.notifyAppReady();
codePush.sync({
updateDialog: true,
installMode: codePush.InstallMode.IMMEDIATE
});
const deviceName = await Storage.get('deviceName');
if (!deviceName) {
await Storage.set('deviceName', DeviceInfo.getDeviceName());
}
}
componentWillMount() {
OneSignal.setLocationShared(true);
OneSignal.inFocusDisplaying(2);
}
render(): React.Node {
const { dispatch, [NAME]: state } = this.props;
console.log(this.props);
return <AppNavigation navigation={{ dispatch, state }} />;
}
}
AppWithNavigationStateObject.propTypes = {
dispatch: PropTypes.func.isRequired,
[NAME]: PropTypes.object.isRequired
};
const AppWithNavigationStateInfo = createReduxContainer(AppNavigation);
const AppWithNavigationState = connect(state => ({
[NAME]: state[NAME]
}))(codePush(codePushOptions)(AppWithNavigationStateInfo));
export { AppWithNavigationState, middleware };
// #flow
// navReducer
import { handleActions } from 'redux-actions';
import { NavigationActions, StackActions } from 'react-navigation';
import { REHYDRATE } from 'redux-persist/constants';
import { AppNavigation } from './Navigation';
import {
CHAT_MAIN,
CHAT_MESSAGE_AREA,
NEW_MESSAGE,
FCLAUNCH,
} from './constants';
const { getStateForAction } = AppNavigation.router;
const initialState = getStateForAction(NavigationActions.init);
const getCurrentRouteName = navState => {
if (Object.prototype.hasOwnProperty.call(navState, 'index')) {
console.log(navState);
return getCurrentRouteName(navState.routes[navState.index]);
}
return navState.routeName;
};
const generateNavigationAction = (state, routeName, params = {}) => {
console.log(routeName);
// Don't navigate to the same screen if is already there.
if (getCurrentRouteName(state) === routeName) {
return state;
}
const nextState = getStateForAction(
NavigationActions.navigate({
routeName,
params
}),
state
);
return nextState || state;
};
export default handleActions(
{
// Custom actions types
[CHAT_MAIN]: state => generateNavigationAction(state, CHAT_MAIN),
[FCLAUNCH]: state => generateNavigationAction(state, FCLAUNCH),
[CHAT_MESSAGE_AREA]: state =>
generateNavigationAction(state, CHAT_MESSAGE_AREA),
[NEW_MESSAGE]: state => generateNavigationAction(state, NEW_MESSAGE),
// overwritten action types from react-navigation
[NavigationActions.NAVIGATE]: (state, { routeName }) =>
generateNavigationAction(state, routeName),
[NavigationActions.BACK]: state => {
const nextState = getStateForAction(NavigationActions.back(), state);
return nextState || state;
},
[NavigationActions.INIT]: state => {
console.error(NavigationActions.INIT);
return state;
},
[NavigationActions.RESET]: (state, { routeName }) => {
console.error(NavigationActions.RESET);
StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName })]
});
return state;
},
[NavigationActions.SET_PARAMS]: (state, { key, params }) => {
const nextState = getStateForAction(
NavigationActions.setParams({
params,
key
}),
state
);
return nextState || state;
},
[NavigationActions.URI]: state => {
console.error(NavigationActions.URI);
return state;
},
// Default initialRouteName
[REHYDRATE]: (state, { payload: { auth } }) => {
const isLogged =
auth &&
auth.token &&
auth.token.length !== 0 &&
auth.refreshToken &&
auth.status &&
auth.refreshToken.length !== 0;
const nextState = isLogged
? state
: generateNavigationAction(state, FCLAUNCH);
return nextState;
}
},
initialState
);
```[enter image description here][2]
[1]: https://i.stack.imgur.com/j5dm8.png
So I fixed my issue:
The createReduxContainer helper from react-navigation-redux-helpers expects three key params: { dispatch, state, ...props }, I wasn't passing the dispatch and state directly but as part of the navigation object passed. So I fixed this by passing missing parameters.
CounterContainer
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PropType from 'prop-types';
import Counter from '../components/Counter';
import * as counterActions from '../store/modules/counter';
import * as postActions from '../store/modules/post';
class CounterContainer extends Component {
handleIncrement = () => {
const { CounterActions } = this.props;
CounterActions.increment();
}
handleDecrement = () => {
const { CounterActions } = this.props;
CounterActions.decrement();
}
addDummy = () => {
const { PostActions } = this.props;
console.log(PostActions);
PostActions.addDummy({
content: 'dummy',
userUID: 123,
});
}
render() {
const { handleIncrement, handleDecrement, addDummy } = this;
const { number } = this.props;
return (
<Counter
onIncrement={handleIncrement}
onDecrement={handleDecrement}
addDummy={addDummy}
number={number}
/>
);
}
}
CounterContainer.propTypes = {
number: PropType.number.isRequired,
CounterActions: PropType.shape({
increment: PropType.func,
decrement: PropType.func,
}).isRequired,
};
export default connect(
state => ({
number: state.counter.number,
}),
dispatch => ({
CounterActions: bindActionCreators(counterActions, dispatch),
PostActions: bindActionCreators(postActions, dispatch),
}),
)(CounterContainer);
PostContainer
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
// import { ListItem } from 'react-native-elements';
import { Text } from 'react-native';
import PropType from 'prop-types';
import Post from '../components/Post';
import * as postActions from '../store/modules/post';
class PostContainer extends Component {
refreshing = () => {}
onRefresh = () => {}
renderItem = ({ item }) => (<Text>{item.content}</Text>)
render() {
const { renderItem } = this;
const { postList } = this.props;
return (
<Post
postList={postList}
renderItem={renderItem}
/>
);
}
}
export default connect(
state => ({
postList: state.post.postList,
}),
dispatch => ({
CounterActions: bindActionCreators(postActions, dispatch),
}),
)(PostContainer);
modules/post
import { createAction, handleActions } from 'redux-actions';
const initialState = {
postList: [{
content: 'test',
userUID: 123,
},
{
content: '123123',
userUID: 123123,
},
],
};
const ADD_DUMMY = 'ADD_DUMMY';
export const addDummy = createAction(ADD_DUMMY, ({ content, userUID }) => ({ content, userUID }));
const reducer = handleActions({
[ADD_DUMMY]: (state, action) => ({
...state,
postList: [action.data, ...state.postList],
}),
}, initialState);
export default reducer;
Clicking the button adds a dummy to the postList.
However, when I click the button, I get
TypeError: Can not read property 'content' of undefined error.
I thought I made it the same as the count-up down tutorial.
But Count Up Down works.
Adding a dummy I made does not work.
Where did it go wrong?
Until I click the Add Dummy Data button
The list is worked.
i change action.data -> actions.payload
const reducer = handleActions({
[ADD_DUMMY]: (state, action) => ({
...state,
postList: [action.payload, ...state.postList],
}),
}, initialState);
It is simply a mistake.
I'm making my first react-native app and I cant seem to bind my actions to props. In the component this.props.actions is an empty, and LoginActions is also an empty object in the mapDispatchToProps function. This leads me to believe its an issue in the action or the connect binding. Can anyone see where I'm going wrong?
Component:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {
View,
StyleSheet,
} from 'react-native';
import {
google,
facebook,
twitter,
} from 'react-native-simple-auth';
import LoginConstants from '../../constants/Login.constants';
import * as LoginActions from '../../actions/Login.actions';
import LoginForm from '../../components/LoginForm';
class Login extends Component {
constructor(props) {
super(props);
alert(JSON.stringify(this.props.actions))
this.loginActions = {
google,
facebook,
twitter,
};
this.loginAction = this.loginAction.bind(this);
}
loginAction(platform) {
alert(JSON.stringify(this.props.actions))
// this.loginActions[platform](LoginConstants[platform])
// .then((info) => {
// alert(info);
// // info.user - user details from the provider
// // info.credentials - tokens from the provider
// }).catch((error) => {
// throw Error(`Error ${error.code}: ${error.description}`);
// });
}
render() {
return (
<LoginForm actions={this.loginActions} loginAction={this.loginAction} />
);
}
}
Login.propTypes = {
actions: PropTypes.object.isRequired,
user: PropTypes.object
};
const styles = StyleSheet.create({
});
const mapStateToProps = (state) => {
return {
user: state.user
};
};
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators(LoginActions, dispatch)
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Login);
Actions:
import LoginConstants from '../constants/Login.constants';
export function getUser(userId) {
return {
type: LoginConstants.actions.getUser,
payload: new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
userId: '123ddgs',
});
}, 2000);
});
};
};
export function saveUser(user) {
return {
type: LoginConstants.actions.saveUser,
payload: new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
userId: '123ddgs',
});
}, 2000);
})
};
};
Reducer:
import LoginConstants from '../constants/Login.constants';
const loginReducers = (state = {
user: {},
prevStates: []
}, action) => {
switch (action.type) {
case LoginConstants.actions.getUser:
state = {
...state,
user: action.payload,
prevStates: [...state.prevStates, action.payload]
};
break;
case LoginConstants.actions.saveUser:
state = {
...state,
user: action.payload,
prevStates: [...state.prevStates, action.payload]
};
break;
}
return state;
};
export default loginReducers;
Store:
import {
createStore,
combineReducers,
applyMiddleware,
} from 'redux';
import thunk from 'redux-thunk';
import promise from 'redux-promise-middleware';
import { createLogger } from 'redux-logger';
import loginReducers from './src/reducers/Login.reducers';
import beerReducers from './src/reducers/Beer.reducers';
export default createStore(
combineReducers({
loginReducers,
beerReducers,
}),
{},
applyMiddleware(createLogger(), thunk, promise())
);
JSON.stringify strips functions from its output and therefore, the actions and dispatcher were not visible in the alert output.