Reputation: 75
i've got some error messages (from my API) in my Redux state that I want to display in to my UI
This is my code:
import * as React from 'react';
import { connect, useSelector } from 'react-redux';
import { createUser } from '../../actions';
import './formStyles.scss';
import{ SignUpFormEx }from './SignUpForm/SignUpForm';
interface IProps {
createUser: any;
errors: any;
}
const UserCreate: React.FC<IProps> = (props) => {
const error = useSelector<IProps, any>(state => state.errors);
const useOnSubmit = (formValues: object) => {
props.createUser(formValues);
}
return (
<div>
<h3>Sign Up</h3>
<SignUpFormEx onSubmit={useOnSubmit}/>
<p>{error}</p>
</div>
)
}
const mapDispatchToProps = (dispatch: any) => ({
createUser: (userInfo: any) => dispatch(createUser(userInfo))
})
export default connect(null, mapDispatchToProps)(UserCreate);
This produces the error:
×
Error: Objects are not valid as a React child (found: object with keys {password, email}). If you meant to render a collection of children, use an array instead.
Not really sure where to go from here.
If i try to convert it to an array i get the error: can't convert null or undefined to object.
i've tried state.errors.username[0]
in useSelector
Probably should note that before data enters the 'error state' the state looks like this:
So it'd probably be better to make my state more like this i'm guessing? then i might not get an undefined error? but i'm not sure how to do that or if its right:
"error": {
"username": [
null
],
"email": [
null
]
}
Reducer:
import { ADD_ERROR, REMOVE_ERROR } from '../actions/types'
export default (state = null, action) => {
const { type, error } = action;
switch (type) {
case REMOVE_ERROR:
return null;
case ADD_ERROR:
return error;
}
return state
}
Combine reducers:
import {combineReducers} from 'redux';
import authReducer from './authReducer';
import {reducer as formReducer} from 'redux-form';
import userReducer from './userReducer'
import errorReducer from './errorReducer';
export default combineReducers({
auth: authReducer,
form: formReducer,
user: userReducer,
errors: errorReducer
});
Upvotes: 1
Views: 2909
Reputation: 29282
Trying to render an object in JSX is not allowed. You need to extract individual properties from the errors
object and display those individual error strings.
Since errors
object looks like this:
const errors = {
username: ['invalid username'],
email: ['invalid email']
}
Calling Object.values(errors)
will return an array that looks like:
[["invalid username"], ["invalid email"]]
calling .flat()
function on this returned array will return the flattened array:
["invalid username", "invalid email"]
So, inside the render function, you could check if errors
is defined. If it is, turn it into an array using Object.values()
and .flat()
function and loop over this array using .map()
function to show the error messages.
{
error && Object.values(error)
.flat()
.map(err => <p>{ err }</p>)
}
Upvotes: 2