I'm trying to pass the state to the reducer, I'm not sure why I can't retrieve the value. I'm getting the following error
× Unhandled Rejection (TypeError): Cannot read property 'data' of
undefined
action
export const getUser = () => {
return async (dispatch) => {
const url = await Axios.get(process.env.REACT_APP_GET_USER);
const response = await url;
const data = response.data; // renders auth:true or auth:false
if(response){
dispatch({type: GET_CURRENT_USER, data})
}
}
}
reducer
const initialState = {
authError: null,
isAuthenticated:localStorage.getItem('auth'),
githubAuth:localStorage.getItem('gitAuth'),
token: null,
user: [],
isAuthenticated2:false,
redirectPath: null
}
case GET_CURRENT_USER:
return({
...state,
isAuthenticated2:action.data.response.auth
})
renders false when this.props.getUser is executed
Front end
import React, { Component } from 'react';
// import axios from 'axios';
import Navbar from './components/layout/Navbar';
import { withStyles } from '#material-ui/core/styles';
import {compose} from 'redux';
import { connect } from 'react-redux';
import { getUser, setCurrentUser} from './actions/';
import setAuthToken from './setAuthToken';
import jwt_decode from 'jwt-decode';
import Axios from './Axios';
import { runInThisContext } from 'vm';
const styles = theme => ({
root: {
flexGrow: 1,
padding: 20
},
paper: {
padding: theme.spacing.unit * 2,
textAlign: 'center',
color: theme.palette.text.secondary,
},
chip: {
margin: theme.spacing.unit,
},
});
class App extends Component {
constructor(props){
super(props);
this.state = {
user: "",
isAuthenticated: false,
}
}
componentWillMount(){
if (localStorage.auth != null) {
// Set auth token header auth
setAuthToken(localStorage.auth);
const token = localStorage.getItem('auth');
// // Decode token and get user info and exp
const decoded = jwt_decode(token);
// console.log(decoded);
// // Set user and isAuthenticated
this.props.setCurrentUser(decoded);
}
this.props.getUser();
console.log(this.props.isAuthenticated2);
}
render() {
const { classes, isAuthenticated } = this.props;
return (
<div className="App">
<Navbar />
</div>
);
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.user.isAuthenticated,
isAuthenticated2: state.user.isAuthenticated2
})
const mapDispatchToProps = (dispatch) => ({
getUser: () => dispatch (getUser()),
setCurrentUser: () => dispatch( setCurrentUser()),
});
export default compose(connect(mapStateToProps, mapDispatchToProps), withStyles(styles))(App);
Edit could it be returning false, because auth:true is an object not an actual boolean ?
As per image error occurs here
action.response.data.auth
and in your code change it to
action.data.response.auth
you should receive data in reducer action.data.auth
case GET_CURRENT_USER:
return({
...state,
isAuthenticated2: action.data.auth
})
Related
React native app
Store(states and backend) is built with axios and redux through redux-axios middleware which requires suffixes _SUCCESS and _FAIL for the Request.
Trying to make API call with redux axios middleware. However, data is not passing to the component. Reducer is executing only Default case for some reason.
action:
import { Actions } from "../../../constants/actions";
export const getNewsBloomberg = () => {
return {
type: Actions.GET_NEWS_BLOOMBERG,
payload: {
client: "newsClient",
request: {
url: "top-headlines?sources=bloomberg",
},
},
};
};
Reducer:
import { Actions } from "../../../constants/actions";
const initialState = {
data: [],
latestUpdate: null,
loading: null,
error: false,
};
export const bloomberg = (state = initialState, action) => {
switch (action.type) {
case Actions.GET_NEWS_BLOOMBERG:
return { ...state, latestUpdate: null, loading: true, error: false };
case Actions.GET_NEWS_BLOOMBERG_SUCCESS:
const data_string = JSON.stringify(action.payload.data);
const data_parsed = JSON.parse(data_string);
const data = data_parsed.articles;
return {
...state,
latestUpdate: new Date(),
loading: false,
data: list,
};
case Actions.GET_NEWS_BLOOMBERG_FAIL:
return {
...state,
latestUpdate: null,
loading: false,
error: "No results found.",
};
default:
return { ...state };
}
};
index.js in Store:
import axios from "axios";
import { multiClientMiddleware } from "redux-axios-middleware";
import storage from "redux-persist/lib/storage";
import { createStore, applyMiddleware } from "redux";
import { persistStore, persistReducer } from "redux-persist";
import reducers from "./reducers";
//import { API_KEY } from "react-native-dotenv";
const persistConfig = {
key: "root",
storage,
whitelist: ["favorites"],
};
const clients = {
stockClient: {
client: axios.create({
baseURL: "https://sandbox.iexapis.com",
responseType: "json",
params: {
token: "Tpk_27c",
},
}),
},
newsClient: {
client: axios.create({
baseURL: "https://newsapi.org/v2",
responseType: "json",
params: {
apiKey: "c7c",
},
}),
},
};
const persistedReducer = persistReducer(persistConfig, reducers);
const store = createStore(
persistedReducer,
// applyMiddleware(client),
applyMiddleware(multiClientMiddleware(clients))
);
const persistor = persistStore(store);
export default { store, persistor };
Reducers are combined and Provider is wrapped to the application in App.js
The component:
import React, { Component } from "react";
import { FlatList, RefreshControl } from "react-native";
import { Content, Text, View } from "native-base";
import NewsItem from "./NewsItem";
import { connect } from "react-redux";
import { getNewsBloomberg } from "../../store/actions/news";
class NewsBloomberg extends Component {
onRefresh = () => this.props.getNewsBloomberg; //merge it
refreshControl = (loading) => (
<RefreshControl
onRefresh={this.onRefresh}
refreshing={loading}
/>
);
render() {
const { data, latestUpdate, loading } = this.props.bloomberg;
return (
<View refreshControl={this.refreshControl(loading)} style={{ flex: 1 }}>
{console.log(loading)}
<FlatList
data={data}
keyExtractor={(key) => key.source.id}
renderItem={({ item, index }) => (
<NewsItem onPress={() => console.log("Pressed")} data={data} />
)}
/>
</View>
);
}
}
const mapStateToProps = (state) => {
console.log(state.bloomberg);
return { bloomberg: state.bloomberg };
};
const mapDispatchToProps = {
getNewsBloomberg,
};
export default connect(mapStateToProps, mapDispatchToProps)(NewsBloomberg);
**I noticed that reducer throws the DEFAULT case only **
Does it mean that action is not dispatching or what?
You're not calling the action creator getNewsBloomberg inside onRefresh.
onRefresh = () => this.props.getNewsBloomberg();
Your mapDispatchToProps is wrong, what mapDispatchToProps does is it gives you dispatch as a first argument by using the higher order component "connect" and by using that you can dispatch your actions in react components,
now what you are doing is you are simply calling actions and not dispatching it,
const mapDispatchToProps = (dispatch) => {
getNewsBloomberg:()=>{dispatch(getNewsBloomberg())},
};
here i am taking dispatch as first argument and invoking the action inside dispatch
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));
}
I have a component that should navigate when a user is authenticated:
componentDidUpdate(prevProps, prevState) {
if (this.props.authenticated) {
this.props.navigation.navigate('Main')
}
}
When I dispatch authLogin it should cause a rerender, which handles the navigation:
export const authLogin = (username, password) => {
return dispatch => {
dispatch(authStart());
axios.post(`http://10.0.2.2:8000/api/v1/rest-auth/login/`, {
username: username,
password: password
})
.then(response => {
var token = response.data.key;
try {
AsyncStorage.setItem('token', token);
} catch (err) {
console.log(err)
}
dispatch(authSuccess(token));
})
.catch(err => {
dispatch(authFail());
console.log(err);
})
}
}
Here is my reducer:
export default function (state = initialState, action) {
switch (action.type) {
case "AUTH_START": {
return {
...state,
authenticating: true,
}
}
case "AUTH_SUCCESS": {
return {
...state,
authenticating: false,
authenticated: true,
token: action.token,
}
}
case "AUTH_FAIL": {
return {
...state,
authenticating: false,
authenticated: false,
}
}
case "AUTH_LOGOUT": {
return {
...state,
authenticating: false,
authenticated: false,
token: null,
}
}
default:
return state
}
}
and action creators:
export const authStart = () => ({type: "AUTH_START"})
export const authSuccess = token => ({type: "AUTH_SUCCESS", token})
export const authFail = () => ({type: "AUTH_FAIL"})
My console is logging that Redux actions are dispatched and that the state is changing, but no rerendering is happening. Here's the whole component:
import React, { Component } from 'react';
import { View, StyleSheet } from 'react-native';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import LoginForm from '../components/LoginForm';
import { authLogin } from '../actions/authActions';
export class LoginScreen extends Component {
handlePress = async (username, password) => {
await this.props.authLogin(username, password);
}
componentDidUpdate(prevProps, prevState) {
if (this.props.authenticated) {
this.props.navigation.navigate('Main')
}
}
render() {
return (
<View style={styles.loginForm}>
<LoginForm handlePress={this.handlePress} {...this.props} />
</View>
);
}
}
const mapState = state => {
return {
authenticated: state.auth.authenticated
}
};
const mapDispatch = dispatch => {
return bindActionCreators({
authLogin,
}, dispatch)
};
export default connect(mapState, mapDispatch)(LoginScreen);
LoginScreen.propTypes = {
authLogin: PropTypes.func.isRequired,
authenticated: PropTypes.bool.isRequired,
};
const styles = StyleSheet.create({
loginForm: {
justifyContent: 'center',
alignItems: 'center',
flex: 1
}
});
and here's my store:
import { combineReducers } from 'redux';
import { createStore, applyMiddleware } from 'redux';
import { logger } from 'redux-logger';
import thunk from 'redux-thunk';
import auth from './auth'
const reducer = combineReducers({auth})
const enhancer = applyMiddleware(thunk, logger)
const store = createStore(reducer, enhancer)
export default store
The store is connected in the Provider in App.js.
I added another reducer, which fixed it instantly. Apparently redux didn't like that combineReducers() only had one argument.
i.e. change
const reducer = combineReducers({auth})
to
const reducer = combineReducers({auth, otherReducer})
Why not put the authentication check and navigation statement inside the handlePress().
handlePress = async (username, password) => {
await this.props.authLogin(username, password);
if (this.props.authenticated) {
this.props.navigation.navigate('Main')
}
}
After the authLogin() dispatches the action and state is updated, you can check the authentication status and navigate the user.
Hope this helps!
I am trying to refresh a react component state based on the props.
I have this file which is the main a child component for a screen:
RoomsList.js
import React from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';
import {connect} from "react-redux";
import {getRooms} from "../../store/actions";
import RoomIcon from "../RoomIcon/RoomIcon";
class RoomList extends React.Component {
componentDidMount() {
this.props.onGetRooms();
}
renderRooms() {
return this.props.rooms.map(room => {
return (
<RoomIcon key={room.id} room={room} />
)
});
}
render() {
return (
<View style={styles.container}>
{ this.props.rooms.length ? this.renderRooms() : <ActivityIndicator /> }
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
width: '100%',
justifyContent: 'space-between',
flexWrap: 'wrap',
}
});
const mapStateToProps = state => {
return {
rooms: state.rooms.rooms
}
};
const mapDispatchToProps = dispatch => {
return {
onGetRooms: () => dispatch(getRooms())
}
};
export default connect(mapStateToProps, mapDispatchToProps)(RoomList);
Rooms Reducer
import { SET_ROOMS } from '../actions/actionTypes';
const initialState = {
rooms: []
};
const roomsReducer = (state = initialState, action) => {
switch (action.type) {
case SET_ROOMS:
return {
...state,
rooms: action.rooms
};
default:
return state;
}
};
export default roomsReducer;
When the state is getting updated within the mapStateToProps function, which I can confirm it is doing as I put a console log inside of there to get the rooms and the object is the updated object.
However, it appears the the render isn't actually getting updated although the state is getting updated. I have tried to do a componentWillReceiveProps and assign the state but the state is never actually updated within here.
Rooms Action
import {SET_ROOMS} from './actionTypes';
import store from "../index";
export const getRooms = () => {
return dispatch => {
fetch("http://localhost/rooms").catch(err => {
console.log(err)
}).then(res => {
res.json();
}).then(parsedRes => {
dispatch(setRooms(parsedRes));
})
}
};
export const addRoom = (roomName, roomDescription) => {
const rooms = store.getState().rooms.rooms;
const room = {
room_name: roomName,
room_description: roomDescription
};
return dispatch => {
fetch("http://localhost/rooms", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(room)
}).catch(err => {
console.log(err)
}).then(res => res.json())
.then(parsedRes => {
rooms.push(parsedRes);
dispatch(setRooms(rooms));
})
}
};
export const setRooms = rooms => {
return {
type: SET_ROOMS,
rooms: rooms
}
};
Initialising Redux Store
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducers from './reducers';
const composeEnhancers = compose;
const store = createStore(reducers, composeEnhancers(applyMiddleware(thunk)));
export default store;
Initializing Reducers
import {combineReducers} from "redux";
import lightsReducer from "./lights";
import roomsReducer from "./rooms";
import modalsReducer from "./modals";
export default combineReducers({
lights: lightsReducer,
rooms: roomsReducer,
modals: modalsReducer
});
Im getting an error like
Actions must be plain objects. Use custom middleware for async actions
while using react redux. Im developing an application with a login functionality. Here is my code.
component
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import Paper from 'material-ui/Paper';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import * as AuthActions from '../../actions/AuthAction';
import {blueGrey50,lightBlue500} from 'material-ui/styles/colors';
const style = {
height: 350,
width: 370,
marginLeft: 80,
marginRight: 380,
marginTop: 80,
marginBottom: 50,
textAlign: 'center',
display: 'inline-block',
backgroundColor: blueGrey50,
paddingTop: 20,
};
const style1 = {
color: lightBlue500
};
const style2 = {
margin: 12,
};
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: ''
};
}
singin=()=>{
console.log('signing in');
this.props.SigninActions.signIn({email:this.state.email,password:this.state.password});
this.setState({email: '',password: '',loading:true});
console.log('done sending to actions');
}
render() {
return (
<div style={{backgroundImage: "url(" + "https://addmeskype.files.wordpress.com/2015/09/d62cb-teenagers-offlinle-online.jpg" + ")",
width:1301, height:654}}>
<Paper style={style} zDepth={2}>
<h1 style={style1}><center>Sign In</center></h1>
<TextField hintText="Email" floatingLabelText="Email" onChange={e=>{this.setState({email:e.target.value})}}/>
<TextField hintText="Password" floatingLabelText="Password" type="password" onChange={p=>{this.setState({password:p.target.value})}}/>
<br/><br/>
<RaisedButton label="Sign In" primary={true} style={style2} onTouchTap={this.singin}/>
</Paper>
{
(this.props.isError)? <span>Email or Password combination is wrong!</span> : <div>No errors</div>
}
</div>
);
}
}
Login.PropTypes = {
isError: PropTypes.bool,
SigninActions: PropTypes.object
}
const mapStateToProps = (state,ownProps) => {
return {
isError: state.isError
}
}
const mapDispatchToProps = (dispatch) => {
return {
SigninActions:bindActionCreators(AuthActions,dispatch)
};
}
export default connect(mapStateToProps,mapDispatchToProps)(Login);
Actions
import axios from 'axios';
import jwtDecode from 'jwt-decode';
import { SIGN_UP_REQUEST, SIGN_IN_REQUEST, GET_USER_DETAILS, UPDATE_USER_DETAILS } from '../constants/user';
export const getUserDetails=(email)=>{
axios.get('http://localhost:3030/user',
email
)
.then((data)=>{
console.log(data);
return ({
type: GET_USER_DETAILS,
user:data.data
});
})
.catch((error)=>{
console.log('err', error);
});
}
export const updateUserDetails=(user)=>{
axios.put('http://localhost:3030/user',
user
)
.then((data)=>{
console.log(data);
return ({
type: UPDATE_USER_DETAILS,
user:data.data
});
})
.catch((error)=>{
console.log('err', error);
});
}
Reducer
import { SIGN_UP_REQUEST, SIGN_IN_REQUEST} from '../constants/user';
const initialState = {
loading: false,
isError: false
};
export default function User(state = initialState, action) {
switch (action.type) {
case SIGN_UP_REQUEST:
return Object.assign({},state,{isError:action.data.isError});
case SIGN_IN_REQUEST:
return Object.assign({},state,{isError:action.data.isError});
default:
return state;
}
}
Rootreducer
import { combineReducers } from 'redux';
import ChatReducer from './ChatReducer';
import UserReducer from './UserReducer';
export default combineReducers({
chat: ChatReducer,
user: UserReducer
})
Store
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import RootReducer from '../reducers/RootReducer';
export default() => {
return createStore(RootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
}
The browser displays the error as
How to overcome this issue?. im quite new to redux.
Vanilla redux only handles plain object actions such as
{ type: SOME_ACTION, ...parameters }
returned synchronously.
You need to look into using middleware like redux-thunk if you want to return Promises or, really, anything other than a plain object from your action creators (or, in this case, handle asynchronous actions).
see this: How to dispatch a Redux action with a timeout?
edit:
The problem is kind of two fold:
first:
export const getUserDetails = (email) => {
axios.put('http://localhost:3030/user', user) .then((data) => {
return {
type: UPDATE_USER_DETAILS,
user:data.data
};
});
});
you're returning an action inside the promise (axios.put) but you're not returning the promise - javascript doesn't work how you're intending it to work. return, in this case, is limited to the nearest parent scope; in this case the promise body. Just given what you have currently, the return type of the getUserDetails action creator is undefined.
// this is still technically *wrong*, see below
export const getUserDetails = (email) => {
// notice the return on the next line
return axios.put('http://localhost:3030/user', user) .then((data) => {
return {
type: UPDATE_USER_DETAILS,
user:data.data
};
});
});
returns a Promise<Action> which still doesn't really solve your problem.
second:
When working with redux-thunk, you wrap your action in a function like
export const getUserDetails = (email) => {
return (dispatch) => {
return axios.put('http://localhost:3030/user', user) .then((data) => {
// this is where the action is fired
dispatch({
type: UPDATE_USER_DETAILS,
user:data.data
});
// if you want to access the result of this API call, you can return here
// the returned promise will resolve to whatever you return here
return data;
});
}
});
when you bind the action creator, it will "unwrap" the creator while keeping the method signature - you use it like you would normally
this.props.getUserDetails("email#domain.com").then((data) => {
// optional resolved promise
})