NextAuth with google calendar API, fs module error - next.js

so i have a component called cita.jsx where i use the Session Provider as so:
import { useState } from "react";
import { useForm } from "react-hook-form";
import { checkout } from "./checkout";
import { google } from "googleapis";
import { useSession } from "next-auth/react";
import { SessionProvider } from "next-auth/react";
// MUI
import TextField from "#mui/material/TextField";
import { LocalizationProvider } from "#mui/x-date-pickers/LocalizationProvider";
import { AdapterDateFns } from "#mui/x-date-pickers/AdapterDateFns";
import { DateTimePicker } from "#mui/x-date-pickers/DateTimePicker";
import LoginTest from "#/components/loginTest/LoginTest";
export default function Cita({ stripePriceID }) {
// console.log(stripePriceID);
const { register, handleSubmit } = useForm();
const { data: session } = useSession();
const createEvent = async () => {
// Load the Google Calendar API
const calendar = google.calendar({
version: "v3",
auth: session.accessToken,
});
// Create a new event
const event = {
summary: "Test Event",
location: "New York",
description: "This is a test event",
start: {
dateTime: "2023-03-01T09:00:00-07:00",
timeZone: "America/Los_Angeles",
},
end: {
dateTime: "2023-03-01T17:00:00-07:00",
timeZone: "America/Los_Angeles",
},
reminders: {
useDefault: true,
},
};
// Insert the new event
await calendar.events.insert({
calendarId: "primary",
resource: event,
});
};
const [value, setValue] = useState(new Date());
return (
<SessionProvider session={session}>
<div className="flex flex-col justify-center h-[475px] md:h-[555px]">
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DateTimePicker
renderInput={(props) => <TextField {...props} />}
label="Fecha y Hora"
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
/>
</LocalizationProvider>
<div
className="overflow-y-auto h-[400px] mt-3
md:scrollbar scrollbar-track-[#d0e7d5] scrollbar-thumb-[#ef8eb2]"
>
<form
onSubmit={handleSubmit(onSubmit)}
className=" flex flex-col space-y-2"
>
<div className=" w-[300px] md:w-[375px] flex flex-col">
<input
{...register("nombre")}
placeholder="Nombre"
className="contactInput"
type="text"
/>
<input
{...register("email")}
placeholder="Email"
className="contactInput"
type="email"
/>
<input
{...register("número")}
placeholder="Número telefónico"
className="contactInput"
type="text"
/>
<input
{...register("medicamentos")}
placeholder="¿Que medicamentos o suplementos consumes?"
className="contactInput"
type="text"
/>
<input
{...register("objectivo")}
placeholder="Objetivo principal"
className="contactInput"
type="text"
/>
<input
{...register("peso")}
placeholder="Peso aproximado"
className="contactInput"
type="text"
/>
<input
{...register("edad")}
placeholder="Edad"
className="contactInput"
type="text"
/>
<input
{...register("estatura")}
placeholder="Estatura promedio"
className="contactInput"
type="text"
/>
<input
{...register("bajar")}
placeholder="¿Por qué quieres bajar de peso?"
className="contactInput"
type="text"
/>
</div>
<LoginTest />
<button
// onClick={() =>
// checkout({
// lineItems: [
// {
// price: `${stripePriceID}`,
// quantity: 1,
// },
// ],
// })
// }
// type="submit"
// role="link"
// className="py-5 px-10 rounded-full text-white bg-[#f28482] font-bold"
>
Pagar Ahora
</button>
</form>
</div>
</div>
</SessionProvider>
);
}
and my logintest: "use client";
import { useSession, signIn, signOut } from "next-auth/react";
export default function LoginTest() {
const { data: session } = useSession();
if (session) {
console.log(session);
return (
<>
Signed in as {session.user.email} <br />
<button onClick={() => signOut()}>Sign out</button>
</>
);
}
return (
<>
Not signed in <br />
<button onClick={() => signIn()}>Sign in</button>
</>
);
}
and then inside my pages/api/auth/[...nextauth].js import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
export default NextAuth({
providers: [
// OAuth authentication providers...
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
],
});
for the life of me, ive been trying to get the calendar api to work with nextjs 13 and i keep getting errors:
i cant seem to figure out how to get this to work. I simply want users, once they authenticate through nextauth, to be able to book an event into my calendar. Please guide me!
./node_modules/gcp-metadata/build/src/gcp-residency.js:19:0
Module not found: Can't resolve 'fs'
Import trace for requested module:
./node_modules/gcp-metadata/build/src/index.js
./node_modules/google-auth-library/build/src/auth/googleauth.js
./node_modules/google-auth-library/build/src/index.js
./node_modules/googleapis/build/src/index.js

Related

How can i export object to render a list of items in NextJs?

I have a form in a page and send that data to my API and store it a json file inside an object i want to export that object to render with a map function all my elements.
add.js:
import React from 'react'
import Layout from '#/components/Layout'
import styles from '#/styles/AddEvent.module.css'
export default function AddEventPage() {
const submitHanlder = (e) => {
e.preventDefault();
const formData = {
title: e.target.title.value,
description: e.target.description.value
}
fetch('/api/events', {
method: 'POST',
body: JSON.stringify(formData)
});
console.log(formData)
}
return (
<Layout title='Add New Event'>
<h1>Add Event</h1>
<div className={styles.container}>
<form className={styles.form} action="" onSubmit={submitHanlder}>
<label className={styles.label} >Title</label>
<input type="text" name="title" />
<label className={styles.label} >Description</label>
<input type="text" name="description"/>
<label className={styles.label}htmlFor="">Date</label>
<input type="date" />
<button type='submit' >Submit</button>
</form>
</div>
</Layout>
)
}
events.js:
const handler = async (req , res) => {
if(req.method === 'POST'){
await fetch('http://localhost:3001/events', {
headers: {
'Content-Type': 'application/json'
},
method: 'POST',
body: req.body
})
return res.status(201).json({ message: 'evento agregado' });
}
return res.status(400).json({ error: 'no se pudo agregar el evento' });
}
export default handler;
This is my db.json: where i store the events i add with my form.
{
"events": [
{
"id": 1,
"title": "Recital coldplay",
"description": "Recital de coldplay en River"
},
{
"title": "Recital metalica",
"description": "Recital de metalica en velez",
"id": 2
}
]
}
How can i export this object above to render all my events in my front end?
This is what i tried:
index.js:
import React from 'react'
import Layout from '#/components/Layout'
import events from '../../db.json'
export default function EventsPage() {
return (
<Layout>
<h1>My Events</h1>
<div>
{events.map((event) => {
return <h1>{event.title}</h1>
})}
</div>
</Layout>
)
}
But i get this error: TypeError: _db_json__WEBPACK_IMPORTED_MODULE_3__.map is not a function
Instead of:
import events from '../../db.json'
Should be:
import { events } from '../../db.json'

Unable to add profile info into firebase collection when signing up (vue | firebase)

I'm getting these two errors
TypeError: firebase__WEBPACK_IMPORTED_MODULE_2__.default.firestore(...).collections is not a function
Cannot read property 'user' of undefined
when trying to add user profile data into firebase collections 'profiles' when signing up. Please help.
This is the template section of my 'EditProfile' page.
<template>
<div class="edit-profile">
<section>
<div class="column">
<div class="header" style="font-weight:bold">
Profile Settings
</div>
<div>
<input
type="text"
class="form-control"
placeholder="Full name"
v-model="profile.name"
/>
<input
type="phone"
class="form-control"
placeholder="Phone"
v-model="profile.phone"
/>
<input
type="text"
class="form-control"
placeholder="Billing Address"
v-model="profile.address"
/>
<input
type="text"
class="form-control"
placeholder="Postcode"
v-model="profile.postcode"
/>
<button
#click="updateProfile"
>
Save changes
</button>
</div>
</div>
</section>
</div>
</template>
Here is my script for the above EditProfile page.I haven't really added the code for edit profile bcuz I'm still unaware on how to do that
<script>
import firebase from "firebase";
require("firebase/auth");
export default {
name: "EditProfile",
data() {
return {
profile: {
fullName: null,
phone: null,
address: null,
postcode: null,
},
};
},
methods: {
updateProfile() {},
},
};
</script>
Here is the template for 'RegisterCustomer' page. Here I will be signing up new users.
<template>
<div class="row">
<transition type="text/x-template" id="register-customer">
<div class="modal-mask">
<div class="modal-wrapper">
<div>
<div class="modal-body">
<slot name="body">
<div class="row">
<div class="col-sm-4 off-set">
<form>
<div #click="$emit('close')">
<span class="close">✖</span>
</div>
<h3>Sign up</h3>
<br />
<div class="form-group">
<input
type="text"
class="form-control"
placeholder="fullName"
v-model="fullName"
/>
</div>
<div class="form-group">
<input
type="email"
class="form-control"
placeholder="Email"
v-model="email"
/>
</div>
<div class="form-group">
<input
type="password"
class="form-control"
placeholder="Password"
v-model="password"
#keyup.enter="
onSubmit();
$emit('close');
"
/>
</div>
<div class="modal-footer">
<slot name="footer">
<button
class="btn btn-primary"
type="button"
#click.prevent="onSubmit"
#click="$emit('close')"
>
Sign up
</button>
</slot>
</div>
</form>
</div>
</div>
</slot>
</div>
</div>
</div>
</div></transition
>
</div>
</template>
This is my sign up code in my RegisterCustomer page. I want to add user info into my profiles collection. For now I want to pass the fullName data into my profiles collection.
<script>
import firebase from "firebase";
import "firebase/auth";
export default {
name: "RegisterCustomer",
data: () => ({
fullName: "",
email: "",
password: "",
}),
methods: {
async onSubmit() {
try {
var { user } = await firebase
.auth()
.createUserWithEmailAndPassword(this.email, this.password)
.then(() => {
firebase
.firestore()
.collection("profiles")
.doc(user.uid)
.update({
fullName: this.fullName,
});
console.log("Document successfully written.");
})
.then(() => {
alert("Registration successful.");
console.log(user.uid);
})
.catch((error) => {
console.log(error.message);
});
// this.$router.push("/customer");
} catch (error) {
console.log("error occured", error.message);
alert(error.message);
}
},
},
};
</script>
You need to import the Firebase services you are importing along with the core Firebase App as shown:
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
If you don't import Firestore that way, it'll result in similar issue. Although it was a typo in your case, it's "collection".
The second error Cannot read property 'user' of undefined, is probably because you are trying to get user property from a Promise. Try refactoring your code like this:
async onSubmit() {
try {
const { user } = await firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
await firebase.firestore().collection("profiles")
.doc(user.uid)
.update({
fullName: this.fullName,
});
console.log("Document successfully written.");
alert("Registration successful.");
console.log(user.uid);
} catch (error) {
console.log("error occured", error.message);
alert(error.message);
}
},
I figured out the answer. All I had to do was change .update() to .set() when creating the profiles collection in RegisterCustomer.
Here is the script for RegisterCustomer. Hope someone finds this useful.
<script>
import firebase from "firebase";
import "firebase/auth";
import "firebase/firestore";
export default {
name: "RegisterCustomer",
data: () => ({
fullName: null,
email: null,
password: null,
address: null,
postcode: null,
}),
methods: {
async onSubmit() {
try {
firebase
.auth()
.createUserWithEmailAndPassword(this.email, this.password)
.then((cred) => {
return firebase
.firestore()
.collection("profiles")
.doc(cred.user.uid)
.set({
email: this.email,
fullName: this.fullName,
address: this.address,
postcode: this.postcode,
})
.then(() => {
console.log("Document successfully written.");
});
})
.then(() => {
alert("Registration successful.");
})
.catch((error) => {
console.log(error.message);
});
this.$router.push("/customer");
} catch (error) {
console.log("Error", error.message);
alert(error.message);
}
},
},
};
</script>

Actions must be plain objects. Use custom middleware for async actions. after adding redux-thunk and using it as a middleware

Actions must be plain objects. Use custom middleware for async actions.
This is the error and this function is pointed
this.props.registerUser(newUser);
see the next code snippet!
redux-thunk is used for referring plain js object but not working
This is my action creator file :
import { GET_ERRORS } from "./types";
import axios from "axios";
// Register User
export const registerUser = userData => dispatch => {
axios
.post("/api/users/register", userData)
.then(res => console.log(res))
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
This is my react registration page :
import React, { Component } from "react";
import PropTypes from "prop-types";
// import { withRouter } from 'react-router-dom';
import classnames from "classnames";
import { connect } from "react-redux";
import { registerUser } from "../../actions/authActions";
class Register extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
password: "",
password2: "",
errors: {}
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({ errors: nextProps.errors });
}
}
onChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
onSubmit(event) {
event.preventDefault();
const newUser = {
name: this.state.name,
email: this.state.email,
password: this.state.password,
confirm_password: this.state.password2
};
this.props.registerUser(newUser);
}
render() {
const { errors } = this.state;
return (
<div className="register">
<div className="container">
<div className="row">
<div className="col-md-8 m-auto">
<h1 className="display-4 text-center">Sign Up</h1>
<p className="lead text-center">
Create your SocioStalker account
</p>
<form noValidate onSubmit={this.onSubmit}>
<div className="form-group">
<input
type="text"
className={classnames("form-control form-control-lg", {
"is-invalid": errors.name
})}
placeholder="Name"
name="name"
value={this.state.name}
onChange={this.onChange}
/>
<div className="invalid-feedback">{errors.name}</div>
</div>
<div className="form-group">
<input
type="email"
className={classnames("form-control form-control-lg", {
"is-invalid": errors.email
})}
placeholder="Email Address"
name="email"
value={this.state.email}
onChange={this.onChange}
/>
<div className="invalid-feedback">{errors.email}</div>
<small className="form-text text-muted">
This site uses Gravatar so if you want a profile image, use
a Gravatar email
</small>
</div>
<div className="form-group">
<input
type="password"
className={classnames("form-control form-control-lg", {
"is-invalid": errors.password
})}
placeholder="Password"
name="password"
value={this.state.password}
onChange={this.onChange}
/>
<div className="invalid-feedback">{errors.password}</div>
</div>
<div className="form-group">
<input
type="password"
className={classnames("form-control form-control-lg", {
"is-invalid": errors.confirm_password
})}
placeholder="Confirm Password"
name="password2"
value={this.state.password2}
onChange={this.onChange}
/>
<div className="invalid-feedback">
{errors.confirm_password}
</div>
</div>
<input type="submit" className="btn btn-info btn-block mt-4" />
</form>
</div>
</div>
</div>
</div>
);
}
}
Register.propTypes = {
registerUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth,
errors: state.errors
});
export default connect(
mapStateToProps,
{ registerUser }
)(Register);
Store config file:
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
import { composeWithDevTools } from "redux-devtools-extension";
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
compose(
composeWithDevTools(),
applyMiddleware(...middleware)
)
);
export default store;
Your store setup logic is wrong. You've got this:
compose(
composeWithDevTools(),
applyMiddleware(...middleware)
)
Instead, it should be:
composeWithDevTools(
applyMiddleware(...middleware)
)
Please see the Redux docs page on "Configuring Your Store" for examples of how to correctly set up middleware and the DevTools Extension.
I'd also encourage you to try out our new redux-starter-kit package. It includes a configureStore function that does all that for you automatically.
Here's how you could simplify your startup file using configureStore:
import {configureStore} from "redux-starter-kit";
import rootReducer from "./reducers";
const store = configureStore({
reducer : rootReducer,
});

Redux State not updating in the Redux DevTool

When I click on a button, it dispatches a function that is meant to login a user and return the user's data. But the Redux store seems not to be updated after the dispatch. When I checked the Redux devtool, It shows that the actions are dispatching appropriately with their payloads but the state remains as the initial state, it doesn't get updated after each dispatched action.
This images below display the action and state of the redux devtool.
Dispatched actions
State display initial state
I don't know I have done wrong, my code are as follows.
userInitialState.js
export default {
user: {},
error: null,
loading: false
};
userLoginAction.js
import axios from 'axios';
import * as types from './actionTypes';
export const signInUserSuccess = payload => ({
type: types.SIGNIN_USER_SUCCESS,
payload
});
export const signingInUser = () => ({
type: types.SIGNING_IN_USER
});
export const signInUserFailure = () => ({
type: types.SIGNIN_USER_FAILURE
});
export const userSignIn = (data) => {
const url = 'https://eventcity.herokuapp.com/api/v1/users/login';
return (dispatch) => {
dispatch(signingInUser());
return axios({
method: 'post',
url,
data
})
.then((response) => {
const user = response.data;
dispatch(signInUserSuccess(user));
})
.catch(() => {
dispatch(signInUserFailure());
});
};
};
userLoginReducer.js
import * as types from '../actions/actionTypes';
import userInitialState from './userInitialState';
const userReducer = (state = userInitialState, action = {}) => {
switch (action.types) {
case types.SIGNING_IN_USER:
return {
...state,
user: {},
error: null,
loading: true
};
case types.SIGNIN_USER_FAILURE:
return {
...state,
user: {},
error: { message: 'Error loading data from the API' },
loading: false
};
case types.SIGNIN_USER_SUCCESS:
return {
...state,
user: action.payload,
error: null,
loading: false
};
default:
return state;
}
};
export default userReducer;
rootReducer.js
import { combineReducers } from 'redux';
import userReducer from './userReducer';
const rootReducer = combineReducers({
userReducer
});
export default rootReducer;
configureStore.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from '../reducer/rootReducer';
const configureStore = () => createStore(rootReducer, composeWithDevTools(applyMiddleware(thunk)));
export default configureStore;
SignInModal.js
import React, { Component } from 'react';
class SignInModal extends Component {
state = {
username: '',
password: ''
};
componentDidMount() {
this.props.userSignIn({});
}
onUsernameChange = e => {
const username = e.target.value;
this.setState(() => ({
username
}));
};
onPasswordChange = e => {
const password = e.target.value;
this.setState(() => ({
password
}));
};
onSubmitForm = e => {
e.preventDefault();
const user = {
username: this.state.username,
password: this.state.password
};
this.props.userSignIn(user);
};
render() {
console.log(this.props.user)
return (
<div>
<div
className="modal fade"
id="exampleModalCenter"
tabIndex="-1"
role="dialog"
aria-labelledby="exampleModalCenterTitle"
aria-hidden="true"
>
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLongTitle">
Sign In Form
</h5>
<button type="button" className="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<form onSubmit={this.onSubmitForm} id="signin">
<div className="form-group">
<label htmlFor="username">Username or Email</label>
<input
type="text"
className="form-control"
name="username"
placeholder="Username or email"
value={this.state.username}
onChange={this.onUsernameChange}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
placeholder="Password"
name="password"
value={this.state.password}
onChange={this.onPasswordChange}
/>
</div>
</form>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-dismiss="modal">
Close
</button>
<button type="submit" className="btn btn-primary" form="signin">
Save changes
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default SignInModal;
SignInModalContainer
import { connect } from 'react-redux';
import { userSignIn } from '../actions/userLoginAction';
import SignInModal from '../components/SignInModal';
const mapStateToProps = state => ({
user: state.userReducer
});
const mapDispatchToProps = dispatch => ({
userSignIn: data => dispatch(userSignIn(data))
});
export default connect(mapStateToProps, mapDispatchToProps)(SignInModal);
I have found the problem. I was using action.types in the switch statement. Instead of using switch(action.type).

Uncaught TypeError when calling an action creator with data from a form input

I am new and would really appreciate your help. I have a form with four inputs (firstName, lastName, position and email) and want to pass the data the user puts in to the state to create an user object. But I always receive this error: Uncaught TypeError: Cannot read property 'firstName' of undefined
Maybe I did map the state wrong? I honestly don't know.
Here is my code:
The form I created which takes the users input:
import React, { Component } from 'react';
import TextField from 'material-ui/TextField';
import { Field, FieldArray, reduxForm} from 'redux-form';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import validate from './validate';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin(); //Needed, otherwise an error message is shown in the console
//Texteingabefeld
const renderTextField = ({input, label, meta: {touched, error}, ...custom}) => (
<TextField
hintText={label}
floatingLabelText={label}
errorText={touched && error}
{...input}
{...custom}
/>
);
const renderUsers = ({fields, meta: { touched, error }}) => (
<div>
<div>
<button className="btn btn-primary"
type="button" onClick={() => fields.push({})}>
<span className="glyphicon glyphicon-plus-sign"/>Add User
</button>
{touched && error && <span>{error}</span>}
</div>
<Field name="firstName" component={renderTextField} label="First Name"/>
<Field name="lastName" component={renderTextField} label="Last Name"/>
<Field name="position" component={renderTextField} label="Position"/>
<Field name="email" component={renderTextField} label="Email"/>
{fields.map((user, index) =>
<div key={index}>
<Field name={`firstName${index}`} component={renderTextField} label="First Name"/>
<Field name={`lastName${index}`} component={renderTextField} label="Last Name"/>
<Field name={`position${index}`} component={renderTextField} label="Position"/>
<Field name={`email${index}`} component={renderTextField} label="Email"/>
<button className="btn btn-xs btn-danger"
type="button"
title="Remove User"
onClick={() => fields.remove(index)}>
<span className="glyphicon glyphicon-minus-sign"/>
</button>
</div>
)}
</div>
);
const UserCreation = props => {
const { handleSubmit, pristine, reset, submitting} = props;
return (
<form onSubmit={handleSubmit}>
<FieldArray name="users" component={renderUsers}/>
<div>
<button className="btn btn-primary btn-success"
type="submit"
disabled={pristine || submitting}>
<span className="glyphicon glyphicon-send" />
Submit
</button>
{' '}
<button type="button"
className="btn btn-primary btn-danger"
disabled={pristine || submitting}
onClick={reset}>
Cancel
</button>
</div>
</form>
);
}
export default reduxForm({
form: 'UserCreationForm',
validate
})(UserCreation);
The Component which fires the action when the user submits the form:
import React, {Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import UserCreation from '../components/UserCreation';
import { addUser } from '../actions/UserActions';
class UserControlPage extends Component {
componentWillMount() {
}
handleSubmit=(values) => {
addUser(values);
}
render() {
return (
<div>
<legend>
<span className="glyphicon glyphicon-user" aria-hidden="true"></span> User creation
</legend>
<UserCreation onSubmit={this.handleSubmit}/>
</div>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({addUser}, dispatch);
}
function mapStateToProps(state) {
return {
users: state.users
}
}
export default connect(mapStateToProps, mapDispatchToProps)(UserControlPage);
The action creator:
import axios from 'axios';
import {ADD_USER} from './index';
export const addUser = (user) => {
return {
type: ADD_USER,
payload: {
// id: id,
firstName: user.payload.firstName,
lastName: user.payload.lastName,
position: user.payload.position,
email: user.payload.email
}
};
}
The reducer:
import {ADD_USER} from '../actions/index';
const INITIAL_STATE = {};
export default function UserReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case ADD_USER:
return [...state, {
// id: action.id,
firstName: action.firstName,
lastName: action.lastName,
position: action.position,
email: action.email
}];
default:
return state;
}
}
The action creator has to get data without the payload, like this:
export const addUser = (user) => {
return {
type: ADD_USER,
payload: {
firstName: user.firstName,
lastName: user.lastName,
position: user.position,
email: user.email
}
}
}
I see a couple things wrong. First of all, you're attaching your data to a payload object inside of your action, but you're not reading from that object in your reducer. So in the reducer, for example, where you have action.firstName, it should actually be action.payload.firstName.
Secondly, what you're returning from the reducer is not right. Your initial state is an object, but you're returning an array. So your state is all kinds of messed up as soon as you mutate state. Try this instead:
import {ADD_USER} from '../actions/index';
const INITIAL_STATE = {};
export default function UserReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case ADD_USER:
return {
...state,
user: action.payload
};
default:
return state;
}
}
Update
I see yet another problem. In this code, you're referencing user.payload, which does not exist.
export const addUser = (user) => {
return {
type: ADD_USER,
payload: {
// id: id,
firstName: user.payload.firstName,
lastName: user.payload.lastName,
position: user.payload.position,
email: user.payload.email
}
};
}
It should be user.firstName, user.lastName, etc.
Thanks guys. Changing the action creator to
export const addUser = (user) => {
return {
type: ADD_USER,
payload: {
firstName: user.firstName,
lastName: user.lastName,
position: user.position,
email: user.email
}
};
}
and the reducer to
const INITIAL_STATE = [];
export default function UserReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case ADD_USER:
return [action.payload, ...state];
default:
return state;
}
}
solved the error.

Resources