Im am getting undefined with mapstatetoprops - javascript

I am trying pass logged data from my redux actions to the front end but keep getting user.name of null or undefined.
This is the front end where I am simply trying to get user.name to appear so that it says Hi user.name(name of persons account).
import React, { Component } from "react";
import { NewPropertyForm, FormPageOne, FormPageTwo, FormPageThree,
FormPageFour } from "../../components/NewPropertyForm";
import { PropertyList } from "../../components/PropertyList";
import { Container, Button, Modal, ModalCard, ModalCardTitle,
ModalBackground, ModalCardFooter, ModalCardHeader, Delete, ModalCardBody
} from 'bloomer';
import StepZilla from "react-stepzilla";
import modal from "./modal-bg.svg";
import "./Manager.css";
import {login} from '../../actions/authActions'
import {connect} from 'react-redux';
import { bindActionCreators } from 'redux'
const steps =
[
{name: 'Step 1', component: <FormPageOne /> },
{name: 'Step 2', component: <FormPageTwo /> },
{name: 'Step 3', component: <FormPageThree /> },
{name: 'Step 4', component: <FormPageFour /> }
]
const modalBG = { backgroundImage: `url(${modal})` }
export class Manager extends Component {
// Setting our component's initial state
state = {
modal: "",
};
modalOpen = () => {
this.setState({ modal: "is-active" })
}
modalClose = () => {
this.setState({
modal: "",
login: "",
})
}
render() {
let { user } = this.props;
return (
<div className="manager">
<Container className="manager-container">
<div className="columns">
<div className="column">
<h1 className="title">Hi {user.name}</h1>
<h2 className="sub-title">You currently have 3 properties</h2>
<h2 className="sub-title">Check out the new applications you
received.</h2>
</div>
<div className="column user-dash-right">
<Button
isColor='primary'
className=""
onClick={this.modalOpen}><p>Create Listing</p></Button>
</div>
</div>
<h1 className="title has-text-centered">My Properties</h1>
<PropertyList />
<div className="new-property-modal">
<Modal className={this.state.modal}>
<ModalBackground />
<ModalCard style={ modalBG } >
<ModalCardBody>
<Delete onClick={this.modalClose} />
<div className='step-progress'>
<StepZilla
steps={steps}
showSteps={false}
nextButtonCls="button is-medium is-primary"
backButtonCls="button is-medium is-primary"
/>
</div>
</ModalCardBody>
</ModalCard>
</Modal>
</div>
</Container>
</div>
);
}
}
const mapStateToProps = ({auth}) => ({
user: auth.user,
authError: auth.authError
});
export default connect(mapStateToProps)(Manager)
This is the actions I have setup
import API from "../utils/API";
import { IS_AUTHENTICATED, AUTHENTICATION_FAILED } from
'../constants/actionTypes';
export const signup = ({name, email, phonenumber, password, role}) =>
async dispatch => {
try {
const {data} = await API.saveUser({
name,
email,
phonenumber,
password,
role
})
dispatch({
type: IS_AUTHENTICATED,
payload: data.user
})
console.log('--success', data);
} catch(error) {
console.error(error);
console.log('Come on work damnit')
}
}
export const login = ({email, password}) => async dispatch => {
try {
const {data} = await API.loginUser({
email,
password
})
dispatch({
type: IS_AUTHENTICATED,
payload: data.user
});
console.log('--success', data.user.name);
} catch(error) {
dispatch({
type: AUTHENTICATION_FAILED,
payload: "Invalid credentials, cannot login"
});
console.error(error);
}
}
export const getAuthenticated = () => async dispatch => {
try {
const {data, error} = await API.getAuthenticated();
console.log(data);
if(data) {
dispatch({
type: IS_AUTHENTICATED,
payload: data
});
} else {
console.log('ssss', error)
}
// if(getUser) login
//else logout
} catch(error) {
//window redirect to login
}
}
export const logout = () => async dispatch => {
try {
// const revoke = await API.logout()
dispatch({
type: IS_AUTHENTICATED,
payload: null
});
//should automatically display logout nav
//or redirect to anther page
} catch(e) {
//just refresh page
}
}
and these are my reducers
import {
IS_AUTHENTICATED,
AUTHENTICATION_FAILED
} from '../constants/actionTypes';
const initialState = {
user: null
}
const authReducer = (state = initialState, {type, payload}) => {
switch(type) {
case IS_AUTHENTICATED:
return {...state, user: payload, userInfo: payload}
case AUTHENTICATION_FAILED:
return {...state, user: null, authError: payload}
default:
return state
}
}
export default authReducer;
As you can see I tried to pass user.name but i keep getting cannot read property of null if I do const { user } = this.props
and i get cannot read property of undefined if i do const { user } = this.state.

I figured it out i justed needed to add
<span>
<h1 className="title">Hi {user.name}</h1>
</span>
and it worked!

Related

Troubles Searching term with Redux Api Rest

I'm having problems filtering info consummed by an api. it is actually the nasa api.
What I Want
Look photos by
Rover's Name (input)
by camera name (input)
by date
I successfully completed the last task but the first input is not bringing the image if I look by the rovers name
Search filter
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { getPhotos } from "../../redux/actions/getPhotos";
import { ErrorAlert } from "./Alerts";
import './SecondFinder.css';
export default function SecondFinder() {
const dispatch = useDispatch();
const [term, setSearchTerm] = useState("");
const [alertERR, setAlertERR] = useState(false);
const submitHandler = (e) => {
e.preventDefault();
dispatch(getPhotos(term));
}
return (
<form onSubmit={submitHandler}>
<div className="searchPhotosByRover">
<label>Search by Rovers Name</label>
<input type="text" placeholder="Search by Rover" value={term} onChange={(e) => setSearchTerm(e.target.value)} />
<button className="btn-primary">Search</button>
{alertERR ? <ErrorAlert /> : ""}
</div>
</form>
)
}
Component:
import React from "react";
import { useSelector } from "react-redux";
import { LoadingAlert, PhotoNotFoundAlert } from "./Alerts";
import Photos from "./Photos";
export default function GridPhotos() {
const state = useSelector((state) => state.result);
const renderPhotos = () => {
if (state.loading) {
return <LoadingAlert />;
} if (state.photos.length === 0) {
return <PhotoNotFoundAlert />;
}
return state.photos.map((photo, index) => {
return <Photos key={index} photo={photo} index={index} />;
});
};
return <div className="gridPhotos">{renderPhotos()}</div>;
}
Actions:
import axios from "axios";
export const getPhotos = (date, term) => async (dispatch, getState) => {
dispatch({
type: "FETCH_PHOTOS_REQUEST"
})
try {
const response = await axios.get(`https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?earth_date=${date}&name=${term}&api_key=${process.env.REACT_APP_API_KEY}&page=1`)
dispatch({
type: "FETCH_PHOTOS_SUCCESS",
payload: response.data.photos
})
} catch (error) {
dispatch({
type: "FETCH_PHOTOS_FAILURE",
error
})
}
}
Reducer
const initialState = {
photos: [],
loading: false,
error: null
}
export const getPhotosReducer = (state = initialState, action) => {
console.log("action", action)
switch (action.type) {
case "FETCH_PHOTOS_REQUEST":
return {
...state,
loading: true,
error: null
}
case "FETCH_PHOTOS_SUCCESS":
return {
...state,
loading: false,
photos: action.payload
}
case "FETCH_PHOTOS_FAILURE":
return {
...state,
loading: false,
error: action.error,
photos: []
}
default:
return state
}
}
I just want to look by the rovers name and bring a picture based on this name
enter image description here

How to render an asynchronous result (array) in a component in react?

I have been doing js for about a month now, and I am writing this program where I am using clarifai API to see which celebrity a person on the photo resembles the most.
I want to pass the output as props to Rank component to render it, but
I get the
Type error: clarifaiResults.map is not a function at App.transformResponse
Basically, the response I want to pass as props is the
const clarifaiResults = response.outputs[0].data.regions[0].data.concepts[0].name;
part that I get in console.log now
I am assuming it's because there is no output yet when the app tries to render the component, but I can't figure out what's wrong with the code. Thank you!
App.js
import React, { Component } from 'react';
import './App.css';
import SignIn from './Component/SignIn/SignIn.js';
import Register from './Component/Register/Register.js';
import Particles from 'react-particles-js';
import Logo from './Component/Logo/Logo.js';
import Navigation from './Component/Navi/Navigation.js';
import ImageLinkForm from './Component/Form/ImageLinkForm.js';
import Rank from './Component/Rank/Rank.js'
import Clarifai from 'clarifai';
import FaceRecognition from './Component/Face/FaceRecognition.js';
import FaceComparison from './Component/Comparison/FaceComparison.js';
const app = new Clarifai.App({
apiKey: 'MYSUPERSECRETKEY'
});
const initialState = {
input: "",
imageUrl: "",
results: [],
route: "SignIn",
user: {
id: "",
name: "",
email: "",
entries: 0,
joined: "",
},
};
const particleOptions = {
particles: {
number: {
value: 40,
density: {
enable: true,
value_area: 800,
},
}
}
}
class App extends Component{
constructor() {
super();
this.state = initialState;
}
transformResponse = (response) => {
const clarifaiResults = response.outputs[0].data.regions[0].data.concepts[0].name;
const results = clarifaiResults.map((ingredient) => ({
ingredients: ingredient.name,
probablitiy: ingredient.value,
}));
this.setState({results: results.celebrityName});
return {results: []};
};
onInputChange = (event) => {
this.setState({input: event.target.value});
}
onSubmit = () => {
this.setState({imageUrl: this.state.input});
app.models
.predict(
Clarifai.CELEBRITY_MODEL,
this.state.input)
.then(response => {
console.log(response.outputs[0].data.regions[0].data.concepts[0].name)
if (response) {
fetch ('http://loclhost:3000', {
method: 'post',
headers: {'Conent-Type' : 'application/json'},
body: JSON.stringify({
input: this.state.user.input
})
})
.then((response) => response.json())
.then(count => {
this.setState(Object.assign(this.state.user, {entries:count}))
})
}
this.transformResponse(response);
})
.catch(err => console.log(err));
};
;
onRouteChange = (route) => {
if (route === 'signout'){
this.setState({isSignedIn: false})
} else if (route ==='home'){
this.setState({isSignedIn: true})
}
this.setState({route: route});
}
render() {
let { isSignedIn, imageUrl, route, results} = this.state;
return (
<div className="App">
<Particles className='particles'
params={particleOptions}
/>
<Navigation isSignedIn={isSignedIn} onRouteChange={this.onRouteChange}/>
{ route ==='home'
? <div>
<Logo />
<Rank
results = {results}/>
<ImageLinkForm
onInputChange={this.onInputChange}
onSubmit={this.onSubmit}
/>
<FaceRecognition
imageUrl={imageUrl}
/>
<FaceComparison
results = {results}
/>
</div>
: (
route === 'SignIn'
? <SignIn onRouteChange={this.onRouteChange}/>
: <Register />
)
}
</div>
);
};
}
export default App;
Rank.js
import React from 'react';
const Rank = ({results}) => {
const prediction = results.map((result) => {
const {ingredients} = result;
return (
<div>
<li className="celebrityName">{ingredients}</li>
</div>
);
});
if (prediction && prediction.length>1) {
return (
<div>
<div className='white f3'>
You look a lot like...
</div>
<div className='white f1'>
{results}
</div>
</div>
);
} else {
return (
<div>
</div>
)
}
};
export default Rank;

Problem using multiple Reducers and Actions Redux

I have a little problem.
I have diferent reducers in different files using a combine reducer, but when i try to use the "different"
INITIAL STATES on these reducers it doesnt apear
For example
Product Reducer -> This is the state that i have to take
const INITIAL_STATE = {
productosInventario: [],
loading: false,
error: ''
Category Reducer -> this is the state for these reducer
const INITIAL_STATE = {
categorias: [],
categoriaActual: '',
loading: false,
error: ''
}
The idea is use both on these component:
Component:
import React, { Component } from 'react'
/* Components */
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import CardItemInventario from '../components/inventario/CardItemInventario'
import * as ProductoActions from '../actions/ProductoActions'
import * as CategoriasActions from '../actions/CategoriasActions'
/* Styles */
import Spinner from '../components/Spinner'
import Fatal from '../components/Fatal'
import '../assets/styles/Containers/Inventario.scss'
class Inventario extends Component {
async componentDidMount() {
await this.props.traerTodosLosProductos();
}
handleChangeCategoria = (e) => {
this.props.cambioCategoriaInventario(e.target.value)
this.props.traerProductosPorCategoriaInventario(e.target.value)
}
/* Mapea todas las categorias disponibles en base de datos */
traerCategoriasInventario = () => this.props.categoriasInventario.map(category => {
let categori = category.categoria
return (
<option
value={categori}
>
{categori}
</option>
)
})
ponerContenido = () => {
if (this.props.loading) {
return (
<Spinner />
)
}
if (this.props.error) {
return (
<Fatal
error={this.props.error} />
)
}
return (
<>
<div className="button-add__cont">
<h1 className="button-add__title">
Inventario
</h1>
<Link to='/agregarinventario' className="button-add__cont--link">
Agregar a Inventario
</Link>
</div>
<select
name="categoriaSelect"
id=""
onChange={this.handleChangeCategoria}
className="selector-categoria"
>
<option value='' defaultValue> - Categoria -</option>
{this.traerCategoriasInventario()}
</select>
<div className="inventario-cont">
{this.imprimirProductos()}
</div>
</>
)
}
imprimirProductos = () => this.props.productosInventario.map(Productos =>
<CardItemInventario
nombre={Productos.nombre}
marca={Productos.marca}
cantidad={Productos.cantidad}
distribuidor={Productos.distribuidor}
precio={Productos.precio}
/>
)
render() {
console.log(this.props)
return (
<>
{this.ponerContenido()}
</>
)
}
}
const mapStateToProps = (reducers) => {
return (
reducers.ProductoReducer,
reducers.CategoriasReducer
)
}
const mapDispatchToProps = {
...ProductoActions,
...CategoriasActions
}
export default connect(mapStateToProps, mapDispatchToProps)(Inventario);
actions ->
productoActions:
import axios from 'axios'
import {
TRAER_TODOS_LOS_PRODUCTOS
} from '../types/ProductoTypes'
import { host_name, port_redux } from '../../../config'
import { CARGANDO, ERROR } from '../types/GlobalTypes'
const axiosConf = {
baseURL: `http://${host_name}:${port_redux}`
}
export const traerTodosLosProductos = () => async (dispatch) => {
dispatch({
type: CARGANDO
})
try {
const res = await axios.get(`/api/productos/get/listar`, axiosConf)
dispatch({
type: TRAER_TODOS_LOS_PRODUCTOS,
payload: res.data
})
} catch (error) {
console.log("Error: " + error)
dispatch({
type: ERROR,
payload: error.message
})
}
}
export const traerProductosPorCategoriaInventario = (categoria) => async (dispatch) => {
try {
const res = await axios.get(`/api/cotizacion/get/productosporcategoria/${categoria}`, axiosConf)
dispatch({
type: TRAER_TODOS_LOS_PRODUCTOS,
payload: res.data
})
} catch (error) {
console.log("Error: " + error)
dispatch({
type: ERROR,
payload: error.message
})
}
}
categoryActions_ >
import axios from 'axios'
import { host_name, port_redux } from '../../../config'
import { CARGANDO, ERROR } from '../types/GlobalTypes'
import {
LISTAR_CATEGORIAS,
CATEGORIA_ACTUAL
} from '../types/CategoriasTypes'
const axiosConf = {
baseURL: `http://${host_name}:${port_redux}`
}
export const traerCategoriasInventario = () => (dispatch) => {
const res = axios.get(`/api/categorias/get/listar`, axiosConf)
console.log(res)
dispatch({
type: LISTAR_CATEGORIAS,
payload: res.data.data
})
}
export const cambioCategoriaInventario = (categoria) => async (dispatch) => {
try {
dispatch({
type: CATEGORIA_ACTUAL,
payload: categoria
})
} catch (error) {
console.log("Error: " + error)
dispatch({
type: ERROR,
payload: error.message
})
}
}
const mapStateToProps = (reducers) => {
return (
reducers.ProductoReducer,
reducers.CategoriasReducer
)
}
It seems like you are having some confusion between state and reducer. The state is the object which contains all of your data. It is just a plain javascript object. The reducer is a function which takes the state object and an action and returns a new state object.
Your setup should look something like this:
const productoReducer = (state = INITIAL_PRODUCTOS, action ) => {
switch ( action.type ) {
case 'TRAER_TODOS_LOS_PRODUCTOS':
/* ... code here ... */
default:
return state;
}
}
const categoriasReducer = (state = INITIAL_CATEGORIAS, action ) => {
switch ( action.type ) {
case 'LISTAR_CATEGORIAS':
/* ... code here ... */
default:
return state;
}
}
export const reducer = combineReducers({
producto: productoReducer,
categorias: categoriasReducer,
})
Here we have two separate reducers for categories and for products, and each gets a separate initial state. We use combineReducers to put them together so now the combined state has properties producto and categorias.
Your component Inventario needs to access a bunch of values from state: categoriasInventario, productosInventario, loading, and error. Rather than passing the state into the component, we use mapStateToProps to extract these values and pass them as props.
const mapStateToProps = (state) => {
return {
categoriasInventario: state.categorias.categorias,
productosInventario: state.productos.productosInventario,
loading: state.categorias.loading || state.productos.loading,
error: state.categorias.error || state.productos.error,
}
}

Set Input Value based on React State after componentDidMount?

I'm using Axios to perform a GET request and then store the information into the {information} property, and then I store all of that in my state. How can I use setState to set the state of the input fields after the compoenntDidMount()?? I've tried a .then() after the this.props.getItemCredential, but it doesn't work because it's not a standard fetch request?
I've also tried to set the state of the input value like: {this.state.profile.credential.itemArray[0].company} and it returns undefined even though I see it in my redux chrome extension as properly being in the state.
I think the issue is that it's returning undefined cause it cannot change the value of the input until the getItemCredential returns, but then how do I wait for it to finish and then adjust the: this.state.(whatever) for each one?
What my component looks like:
import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
import TextFieldGroup from '../../common/TextFieldGroup';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { getItemCredential, getCurrentProfile } from '../../../actions/profileActions';
import Spinner from '../../common/Spinner';
class EditInfo extends Component {
constructor(props) {
super(props);
this.state = {
company: '',
title: '',
location: '',
errors: {},
disabled: false
}
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentDidMount() {
this.props.getItemCredential(this.props.match.params.id)
this.props.getCurrentProfile()
}
onChange = (e) => {
this.setState({[e.target.name]: e.target.value});
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({errors: nextProps.errors});
}
}
onSubmit = (e) => {
e.preventDefault();
const itemData = {
company: this.state.company,
title: this.state.title,
location: this.state.location,
}
}
render() {
const { errors } = this.state;
const { profile, loading } = this.props.profile;
const { credential } = this.props.profile;
let editContent;
if (profile === null || loading) {
editContent = <Spinner />
} else {
editContent = (
<React.Fragment>
<div>
<form onSubmit={this.onSubmit}>
<TextFieldGroup
placeholder={this.state.company}
name="company"
value={this.state.company}
onChange={this.onChange}
error={errors.company}
required
/>
<TextFieldGroup
placeholder="* Job Title"
name="title"
value={this.state.title}
onChange={this.onChange}
error={errors.title}
required
/>
<TextFieldGroup
placeholder="Location"
name="location"
value={this.state.location}
onChange={this.onChange}
error={errors.location}
required
/>
<div class="col-xl-4 col-lg-4 col-md-4 col-sm-12 text-center my-auto">
<input type="submit" value="Submit" class="button text-center m-auto add-credentials-button mt-4" />
</div>
</form>
</div>
);
}
return (
<div>
{editContent}
</div>
)
}
}
EditInfo.propTypes = {
profile: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
getItemCredential: PropTypes.func.isRequired,
getCurrentProfile: PropTypes.func.isRequired,
credential: PropTypes.object.isRequired
}
const mapStateToProps = state => ({
profile: state.profile,
credential: state.credential,
errors: state.errors
});
export default connect(mapStateToProps, { addExperience, getExperienceCredential, getCurrentProfile })(withRouter(EditExperience));
Here is what my state markup looks like:
profile: {
credential: {
itemArray: [
0: {
title: 'Some entry',
company: 'Some entry',
Location: 'some entry'
}
]
}
}
Here is the axios request I'm making:
export const getItemCredential = (id) => dispatch => {
dispatch(setProfileLoading());
axios.get(`/profile/item-credential/${id}`)
.then(res =>
dispatch({
type: GET_ITEM_CREDENTIAL,
payload: res.data
})
)
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
}
Here is what my reducer looks like:
import { GET_PROFILE, PROFILE_LOADING, GET_ITEM_CREDENTIAL } from '../actions/types';
const initialState = {
profile: null,
credential: null,
loading: false
}
export default function(state = initialState, action) {
switch(action.type) {
case PROFILE_LOADING:
return {
...state,
loading: true
}
case GET_PROFILE:
return {
...state,
profile: action.payload,
loading: false
}
case GET_ITEM_CREDENTIAL:
return {
...state,
credential: action.payload
}
default:
return state;
}
}
You can do a .then if you change getItemCredential so it returns a Promise:
export const getItemCredential = (id) => dispatch => {
dispatch(setProfileLoading());
return axios.get(`/profile/item-credential/${id}`)
.then(res => {
dispatch({
type: GET_ITEM_CREDENTIAL,
payload: res.data
});
return res.data;
})
.catch(err => {
dispatch({
type: GET_ERRORS,
payload: err.response.data
});
throw err;
});
}
Notice the added return in getItemCredential. Also, notice that res.data is returned from the Promise so that it can be accessed by your component that awaits it. I also re-threw the caught error so that the Promise continues in the rejected state instead of resolving to undefined.

React Redux Firebase: firebase.auth(...).signOut(...).then(...).error is not a function

This one particular firebase function hasn't worked for me when calling it as an action. Login, edit username, register, all of those work fine... except logout.
After looking at some tutorials and Google's own documentation, I thought this function would work like all the other firebase-auth functions I've implemented.
Here's what my actions to the db look like:
/* AuthUser.js */
export const login = credentials => {
return (dispatch, getState, { getFirebase }) => {
const firebase = getFirebase();
firebase
.auth()
.signInWithEmailAndPassword(credentials.email, credentials.password)
.then(() => {
dispatch({ type: LOGIN_SUCCESS });
dispatch(push('/home'));
})
.catch(err => {
dispatch({ type: LOGIN_FAIL, err });
});
};
};
export const logout = () => {
return (dispatch, getState, { getFirebase }) => {
const firebase = getFirebase();
firebase
.auth()
.signOut()
.then(() => {
dispatch({ type: LOGOUT_SUCCESS });
dispatch(push('/login'));
}) /* ERROR POINTS RIGHT AT THIS LINE */
.error(err => {
dispatch({ type: LOGOUT_FAIL, err });
});
};
};
export const register = user => {
return (dispatch, getState, { getFirebase }) => {
const firebase = getFirebase();
firebase
.auth()
.createUserWithEmailAndPassword(user.email, user.password)
.then(res => {
return res.user.updateProfile({
displayName: user.displayName,
});
})
.then(() => {
dispatch({ type: REGISTER_SUCCESS });
dispatch(push('/login'));
})
.catch(err => {
dispatch({ type: REGISTER_FAIL, err });
});
};
};
export const save = displayName => {
return (dispatch, getState, { getFirebase }) => {
const firebase = getFirebase();
const user = firebase.auth().currentUser;
if (displayName !== '') {
user
.updateProfile({
displayName,
})
.then(() => {
dispatch({ type: SETTINGS_NAME_CHANGED });
dispatch(push('/home'));
})
.catch(err => {
dispatch({ type: SETTINGS_ERROR, err });
});
} else {
dispatch({ type: SETTINGS_LEFT_ALONE });
dispatch(push('/home'));
}
};
};
Here is how I'm setting up my connects in the Component that calls some of these functions.
/* Settings.js */
import React from 'react';
import { /* Some Stuff */ } from 'reactstrap';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import 'someStyles.scss';
import { logout, save } from '../store/actions/authUser';
class Settings extends React.Component {
constructor(props) {
super(props);
this.state = {
displayName: '',
};
}
/* This doesn't! */
onLogout = event => {
event.preventDefault();
this.props.logout();
};
/* This works! */
onSubmit = event => {
event.preventDefault();
this.props.save(this.state.displayName);
};
onChange = event => {
this.setState({
[event.target.id]: event.target.value,
});
};
render() {
const { displayName } = this.state;
return (
<Container className=".settingsBody">
<nav>
<Nav>
<NavItem>
<NavLink href="https://github.com">GitHub</NavLink>
</NavItem>
<NavItem>
<NavLink>
<div onClick={this.onLogout.bind(this)}>Logout</div>
</NavLink>
</NavItem>
</Nav>
</nav>
<Form onSubmit={this.onSubmit.bind(this)}>
<FormGroup>
<Label for="displayName">Change Display Name</Label>
<Input
type="text"
name="text"
id="displayName"
placeholder={this.props.auth.displayName}
value={displayName}
onChange={this.onChange}
/>
</FormGroup>
<Button color="primary">Save Settings</Button>
</Form>
</Container>
);
}
}
Settings.propTypes = {
logout: PropTypes.func.isRequired,
save: PropTypes.func.isRequired,
authError: PropTypes.string,
auth: PropTypes.object,
};
const mapStateToProps = state => {
return {
authError: state.auth.authError,
auth: state.firebase.auth,
};
};
const mapDispatchToProps = dispatch => {
return {
logout: () => dispatch(logout()),
save: displayName => dispatch(save(displayName)),
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Settings);
React throws this error: TypeError: firebase.auth(...).signOut(...).then(...).error is not a function Yet other functions run as expected when ran.
Is there something I'm missing? The code will attempt to navigate to the page I want but throws the error before that page properly mounts.
Promises doesn't have .error callback, it should be .catch.
Read about Using Promises

Categories