User not showing in local storage - node.js

I was working on my first MERN project and was trying to use local storage with context API, but the data is not getting reflected in the local storage and no error is getting reflected either in the console.
When I log in as a user, the local storage still stays empty.
Below is my Context.js code
import { createContext, useEffect, useReducer, useState } from "react";
import Reducer from "./Reducer";
const INITIAL_STATE = {
user: JSON.parse(localStorage.getItem("user")) || null,
isFetching: false,
error: false,
};
export const Context = createContext(INITIAL_STATE);
export const ContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(Reducer, INITIAL_STATE);
const [user, setItems] = useState([]);
useEffect(() => {
localStorage.setItem('user', JSON.stringify(state.user));
}, [state.user]);
return (
<Context.Provider
value={{
user: state.user,
isFetching: state.isFetching,
error: state.error,
dispatch,
}}
>
{children}
</Context.Provider>
);
};
Below is my login.jsx code
import { Link } from "react-router-dom";
import "./login.css"
import { useContext, useRef } from "react";
import axios from "axios";
import { Context } from "../../../context/Context";
export default function Login() {
const userRef = useRef();
const passwordRef = useRef();
const { user, dispatch, isFetching } = useContext(Context);
const handleSubmit = async (e) => {
e.preventDefault();
dispatch({ type: "LOGIN_START" });
try {
const res = await axios.post("/auth/login", {
username: userRef.current.value,
password: passwordRef.current.value,
});
dispatch({ type: "LOGIN_SUCCESS", payload: res.data });
} catch (err) {
dispatch({ type: "LOGIN_FAILURE" });
}
};
console.log(isFetching)
return (
<div className="login">
<span className="loginTitle">Login</span>
<form className="loginForm" onSubmit={handleSubmit}>
<label>Username</label>
<input className="loginInput" type="text" placeholder="Enter your username..." ref=
{userRef} />
<label>Password</label>
<input className="loginInput" type="password" placeholder="Enter your
password..."
ref={passwordRef} />
<button className="loginButton" type="submit">Login</button>
</form>
<button className="loginRegisterButton">
<Link className="link" to="/register">Register</Link>
</button>
</div>
);
}
I have tried googling it out for 2 hours straight, but am not able to get the mistake from which it is arising. Any help is highly appreciated!!

import { createContext, useEffect, useReducer, useState } from "react";
import Reducer from "./Reducer";
const INITIAL_STATE = {
user: JSON.parse(localStorage.getItem("user")) || null,
isFetching: false,
error: false,
};
export const Context = createContext(INITIAL_STATE);
export const ContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(Reducer, INITIAL_STATE);
const [user, setItems] = useState([]);
useEffect(() => {
console.log(state.user);
localStorage.setItem('user', JSON.stringify(state.user));
}, [state.user]);
return (
<Context.Provider
value={{
user: state.user,
isFetching: state.isFetching,
error: state.error,
dispatch,
}}
>
{children}
</Context.Provider>
);
};
I think you'd better check first if user data is in there.

Related

Not able to display Redis data from Apollo Client

I am trying to add a post in Graphql and storing it in Redis, below is the code:
Client
NewPost.js:
import { useMutation, useQuery } from "#apollo/client";
import { UPLOAD_IMAGE } from "./mutation";
import { useState } from "react";
function NewPost() {
const [posterName, setPosterName] = useState(null);
const [uploadImage] = useMutation(UPLOAD_IMAGE);
const [url, setUrl] = useState(null);
const [description, setDescription] = useState(null);
const addPost = () => {
uploadImage({
variables: {
url: url,
description: description,
posterName: posterName,
},
});
};
return (
<div className="App">
Url--- <input onChange={(e) => setUrl(e.target.value)} />
<br />
PosterName--- <input onChange={(e) => setPosterName(e.target.value)} />
<br />
Description ---
<input onChange={(e) => setDescription(e.target.value)} />
<br />
<button onClick={() => addPost()}>Add Post</button>
</div>
);
}
export default NewPost;
mutation.js:
import { gql } from "#apollo/client";
export const UPLOAD_IMAGE = gql`
mutation uploadImage($url: String, $description: String, $posterName: String) {
uploadImage(post: { url: $url, description: $description , posterName: $posterName }) {
url
posterName
description
}
}
`;
App.js:
import React from 'react';
import {NavLink, BrowserRouter as Router, Route} from 'react-router-dom';
import UserPosts from './components/UserPosts';
import Bin from './components/Bin';
import Home from './components/Home';
import NewPost from './components/NewPost';
import UnsplashPosts from './components/UnsplashPosts';
import {
ApolloClient,
HttpLink,
InMemoryCache,
ApolloProvider
} from '#apollo/client';
const client = new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: 'http://localhost:4000'
})
});
function App() {
return (
<ApolloProvider client={client}>
<Router>
<div>
<header className='App-header'>
<h1 className='App-title'>
GraphQL Lab5
</h1>
<nav>
<NavLink className='navlink' to='/'>
Home
</NavLink>
<NavLink className='navlink' to='/my-bin'>
Bin
</NavLink>
<NavLink className='navlink' to='/my-posts'>
Posts
</NavLink>
<NavLink className='navlink' to='/new-post'>
Create New Post
</NavLink>
</nav>
</header>
<Route exact path='/' component={UnsplashPosts} />
<Route path='/my-bin/' component={Bin} />
<Route path='/my-posts' component={UserPosts} />
<Route path='/new-post' component={NewPost} />
</div>
</Router>
</ApolloProvider>
);
}
export default App;
Server
index.js:
const {ApolloServer, gql} = require('apollo-server');
const axios = require('axios');
const uuid = require('uuid');
const bluebird = require('bluebird');
const redis = require('redis')
const client = redis.createClient();
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const typeDefs = gql`
type Query {
photos: [Photo]
post: [ImagePost]
unsplashImages: [ImagePost]
userPostedImages: [ImagePost]
}
type Photo {
id: String
username: String
}
type ImagePost {
id: String
url: String!
posterName: String!
description: String
userPosted: Boolean
binned: Boolean
}
type Mutation {
uploadImage(
url: String
description: String
posterName: String
): ImagePost
}
`;
const resolvers = {
Query: {
unsplashImages: async (_, args) => {
const { data } = await axios.get('https://api.unsplash.com/photos/?client_id=2zceQd7D4SraKoqW_GjPzXboSup3TKRIPk7EXfJBcAs');
const a = data.map(imagePost => {
return {
id: imagePost.id,
posterName: imagePost.user.name,
url: imagePost.urls.raw,
description: imagePost.description,
}
})
return a;
},
userPostedImages: async (_,args) => {
let history = await client.lrangeAsync("postedImagesList",0,100).map(JSON.parse);
return history;
}
},
Mutation: {
uploadImage: async (_,args) => {
//const { data } = await axios.get('https://api.unsplash.com/photos/?client_id=2zceQd7D4SraKoqW_GjPzXboSup3TKRIPk7EXfJBcAs');
const newPost = {
id: uuid.v4(),
url: args.url,
description: args.description,
posterName: args.posterName,
binned: false,
userPosted: true,
}
await client.lpushAsync("postedImagesList",JSON.stringify(newPost));
}
}
};
const server = new ApolloServer({typeDefs, resolvers});
server.listen().then(({url}) => {
console.log(`🚀 Server ready at ${url} 🚀`);
});
When I try to add a post only using the server I am able to do so in the playground, but when I click on Add post in frontend, the post does not get added to redis and does not show up.

What is the best way to store user info in React Redux?

I am learning React Redux. I am having a very difficult time learning it. Please excuse how bad my code is because I only started learning a few days ago I want to have a store for the logged in user. It will contain their username, email, etc. Currently I am not using sessions/cookies nor even a database for the users. I am simply trying to learn Redux.
I need help with a few things. The state can contain many objects. I just want one object for the user. And because I am currently having trouble with that, how do I display the username without having to .map() because the state is an array?
Here is my current code for the actions/reducers.
import { combineReducers } from "redux";
const defaultUser = [];
// Actions
const LOGIN_USER = "LOGIN_USER";
export function loginUser(user) {
return {
type: LOGIN_USER,
user,
};
}
// Reducers
function user(state = defaultUser, action) {
switch (action.type) {
case LOGIN_USER:
return [
...state,
{
username: action.user,
},
];
default:
return state;
}
}
const usersStore = combineReducers({ user });
export default usersStore;
Here is the App.js file where I want a user to type a username in the input box, then print out their username.
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import "./App.css";
import { Sidebar } from "./components/Sidebar/Sidebar";
import { Content } from "./components/Content/Content";
import { loginUser } from "./store";
const App = () => {
const [user, setUser] = useState("");
const selectedUser = useSelector((state) => state.user);
const dispatch = useDispatch();
const handleSubmit = (event) => {
event.preventDefault();
dispatch(loginUser(user));
setUser("");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
onChange={(e) => setUser(e.target.value)}
value={user}
/>
<br />
<input type="submit" />
</form>
<br />
<br />
{selectedUser.map((selectUser) => (
<li key={selectUser.username}>
<h3>{selectUser.username}</h3>
</li>
))}
<Content />
</div>
);
};
I figured it out on my own. With my new setup, all I have to do is type {user.username} to get the username of the logged in user. I am fetching it with useSelector().
It basically sets the username as a state temporarily, then sends it over to the store via dispatch, then empties out the state afterwards.
I had to change the initialstate to an object with "profile" inside it (instead of using an array)
I then had to map the state to props of the component I want it to display in, using a function, and then use connect() when exporting it.
Here's my new component code, the bottom few lines are the most important:
import React, { useState } from "react";
import { connect, useDispatch, useSelector } from "react-redux";
import "./App.css";
import { Sidebar } from "./components/Sidebar/Sidebar";
import { Content } from "./components/Content/Content";
import { loginUser } from "./store";
const App = (props) => {
const [stateUser, stateSetUser] = useState("");
const user = useSelector((state) => state.user.profile);
const dispatch = useDispatch();
const handleSubmit = (event) => {
event.preventDefault();
dispatch(loginUser(stateUser));
stateSetUser("");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
onChange={(e) => stateSetUser(e.target.value)}
/>
<input type="submit"></input>
</form>
{user.username}
<Content />
</div>
);
};
const mapStateToProps = (state) => {
return {
profile: state.user.profile,
};
};
export default connect(mapStateToProps)(App);
My reducer/actions file: (changes in initialstate are most important)
import { combineReducers } from "redux";
const initialState = {
profile: {
username: "",
email: "",
profileImage: "",
},
};
// Actions
const LOGIN_USER = "LOGIN_USER";
export function loginUser(user) {
return {
type: LOGIN_USER,
user,
};
}
// Reducers
function user(state = initialState, action) {
switch (action.type) {
case LOGIN_USER:
return {
...state,
profile: { username: action.user },
};
default:
return state;
}
}
const usersStore = combineReducers({ user });
export default usersStore;

× TypeError: Object(...) is not a function. Mern stack post request with fetch not working

I am getting this error with a MERN stack that I m working on
when trying to send a post request to create a new user in MongoDB. I am getting this error. I am not sure why this is happening and it is discouraging to say the least. I've only been coding for about 6 months
TypeError: Object(...) is not a function
handleSubmit
src/components/auth/RegistrationForm.js:27
24 | email: {email},
25 | password: {password}
26 | }
> 27 | create(user).then((response) => {
| ^ 28 | if (response.error) {
29 | console.log(response)
30 | }
here is the registration form
import React, { Fragment, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { toast } from 'react-toastify';
import { Button, CustomInput, Form, FormGroup, Input, Label } from 'reactstrap';
import Divider from '../common/Divider';
import SocialAuthButtons from './SocialAuthButtons';
import withRedirect from '../../hoc/withRedirect';
import axios from 'axios'
import create from '../../user/api-user';
const RegistrationForm = ({ setRedirect, setRedirectUrl, layout, hasLabel }) => {
// State
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [isAccepted, setIsAccepted] = useState(false);
const [isDisabled, setIsDisabled] = useState(true);
// Handler
const handleSubmit = e => {
e.preventDefault()
const user = {
email: {email},
password: {password}
}
create(user).then((response) => {
if (response.error) {
console.log(response)
}
})
toast.success(`Successfully registered as ${email}`);
setRedirect(true);
};
useEffect(() => {
setRedirectUrl(`/authentication/${layout}/login`);
}, [setRedirectUrl, layout]); // the array are dependencies that trigger the function setREdirectUrl. good to know
useEffect(() => {
setIsDisabled( !email || !password || !confirmPassword || !isAccepted || password !== confirmPassword);
}, [ email, password, confirmPassword, isAccepted]);
return (
<>
<Form onSubmit={handleSubmit}>
<FormGroup>
{hasLabel && <Label>Email address</Label>}
<Input
placeholder={!hasLabel ? 'Email address' : ''}
value={email}
onChange={({ target }) => setEmail(target.value)}
type="email"
/>
</FormGroup>
<div className="form-row">
<FormGroup className="col-6">
{hasLabel && <Label>Password</Label>}
<Input
placeholder={!hasLabel ? 'Password' : ''}
value={password}
onChange={({ target }) => setPassword(target.value)}
type="password"
/>
</FormGroup>
<FormGroup className="col-6">
{hasLabel && <Label>Confirm Password</Label>}
<Input
placeholder={!hasLabel ? 'Confirm Password' : ''}
value={confirmPassword}
onChange={({ target }) => setConfirmPassword(target.value)}
type="password"
/>
</FormGroup>
</div>
<CustomInput
id="customCheckTerms"
label={
<Fragment>
I accept the <Link to="#!">terms</Link> and <Link to="#!">privacy policy</Link>
</Fragment>
}
checked={isAccepted}
onChange={({ target }) => setIsAccepted(target.checked)}
type="checkbox"
/>
<FormGroup>
<Button color="primary" block className="mt-3" disabled={isDisabled}>
Register
</Button>
</FormGroup>
<Divider className="mt-4">or register with</Divider>
</Form>
<div>
<Form>
<SocialAuthButtons />
</Form>
</div>
</>
);
};
RegistrationForm.propTypes = {
setRedirect: PropTypes.func.isRequired,
setRedirectUrl: PropTypes.func.isRequired,
layout: PropTypes.string,
hasLabel: PropTypes.bool
};
RegistrationForm.defaultProps = {
layout: 'basic',
hasLabel: false
};
export default withRedirect(RegistrationForm);
here is the api-user.js
import React from 'react'
const create = async (user) => {
try {
let response = await fetch('/api/user/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
return await response.json()
} catch(err) {
console.log(err)
}
}
export default { create }
You are exporting the create method in an Object. So, you simply can't invoke the function like this.
The solution is:
import { create } from '../../user/api-user';
Or, you can do this:
import UserApi from '../../user/api-user';
UserApi.create(user).then(...).catch(...);

_id is missing after doing actions

i'm currently creating my first MERN App, and everything is going well, until something happened, and i'm going my try to explain because i need help !
What i'm doing is a facebook clone, where you can post something, you can delete your post and you can update your post, the logic is simple, i call dispatch to pass the data to the actions, the actions pass the data to the backend, and the backend return something to me and it saves in my store, because i'm using redux
The problem is that, when i have 2 post, and i want to delete a post, or maybe i want to edit it, the other post dissapears, it's like it loses its id and then loses the information, then i can't do anything but reaload the page, and it happens always
this is how it looks like, everything fine
Then, after trying to edit a post, the second one lost its information, and in the console, it says that Warning: Each child in a list should have a unique "key" prop, and i already gave each post the key={_id}, but the post lost it and i don't know how
Here's the code
Posts.js
import React, { useState } from "react";
import "./Posts.css";
import moment from "moment";
// Icons
import { BiDotsVertical, BiLike } from "react-icons/bi";
import { MdDeleteSweep } from "react-icons/md";
import { AiFillLike } from "react-icons/ai";
import { GrClose } from "react-icons/gr";
// Calling actions
import { deletePost, } from "../actions/posts.js";
// Gettin The Data From Redux
import { useSelector, useDispatch } from "react-redux";
const Posts = ({ setCurrentId }) => {
const [animation, setAnimation] = useState(false);
const [modal, setModal] = useState(false);
const [modalPost, setModalPost] = useState({});
// Getting The Posts
const posts = useSelector(state => state.posts);
const dispatch = useDispatch();
// Showing And Hiding Modal Window
const ModalWindow = post => {
setModalPost(post);
setModal(true);
};
// Liking the post
// const Like = id => {
// dispatch(giveLike(id));
// setAnimation(!animation);
// };
if (!posts.length) {
return <div>Loading</div>;
} else {
return (
<div className="Posts">
{/* // Modal window for better look to the post */}
{/* {modal && (
<div className="modalWindow">
<div className="container">
<div className="container-image">
<img src={modalPost.image} alt="" />
</div>
<div className="information">
<div className="container-information">
<div className="data-header">
<h2>
User <br />{" "}
<span style={{ fontWeight: "400" }}>
{moment(modalPost.createdAt).fromNow()}
</span>
</h2>
<span className="data-icon" onClick={() => setModal(false)}>
<GrClose />
</span>
</div>
<div className="message">
<h2>{modalPost.title}</h2>
<p>{modalPost.message}</p>
</div>
</div>
</div>
</div>
</div>
)} */}
{/* */}
{posts.map(post => {
const { _id, title, message, image, createdAt, likes } = post;
return (
<div className="Posts-container" key={_id}>
<div className="Fit">
<div className="Fit-stuff">
<h2 className="Fit-stuff_title">
User <br />{" "}
<span style={{ fontWeight: "400" }}>
{moment(createdAt).fromNow()}
</span>
</h2>
<a
className="Fit-stuff_edit"
href="#form"
onClick={() => setCurrentId(_id)}
>
<BiDotsVertical />
</a>
</div>
<div className="Fit-data">
<h2 className="Fit-data_title">{title}</h2>
<p className="Fit-data_message">{message}</p>
{image ? (
<div className="Fit-img">
<img
onClick={() => ModalWindow(post)}
src={image}
alt=""
/>
</div>
) : (
<div></div>
)}
</div>
<div className="Fit-shit">
<span>
{animation ? (
<AiFillLike className="fullLightBlue" />
) : (
<BiLike />
)}
{likes}
</span>
<span onClick={() => dispatch(deletePost(_id))}>
<MdDeleteSweep />
</span>
</div>
</div>
</div>
);
})}
</div>
);
}
};
export default Posts;
The form where i call update and create Post
import React, { useState, useEffect } from "react";
import Filebase from "react-file-base64";
// For the actions
import { useDispatch, useSelector } from "react-redux";
import { createPost, updatePost } from "../actions/posts.js";
import {
Wrapper,
FormContainer,
Data,
DataInput,
SecondDataInput,
FormContainerImg,
FormContainerButtons,
Buttons
} from "./FormStyled.js";
const Form = ({ currentId, setCurrentId }) => {
const [formData, setFormData] = useState({
title: "",
message: "",
image: ""
});
const specificPost = useSelector(state =>
currentId ? state.posts.find(p => p._id === currentId) : null
);
// Sending The Data And Editing The data
const dispatch = useDispatch();
useEffect(() => {
if (specificPost) setFormData(specificPost);
}, [specificPost]);
// Clear Inputs
const clear = () => {
setCurrentId(0);
setFormData({ title: "", message: "", image: "" });
};
const handleSubmit = async e => {
e.preventDefault();
if (currentId === 0) {
dispatch(createPost(formData));
clear();
} else {
dispatch(updatePost(currentId, formData));
clear();
}
};
return (
<Wrapper>
<FormContainer onSubmit={handleSubmit}>
<Data>
<DataInput
name="title"
maxLength="50"
placeholder="Title"
type="text"
value={formData.title}
onChange={e => setFormData({ ...formData, title: e.target.value })}
/>
<SecondDataInput
name="message"
placeholder="Message"
maxLength="300"
value={formData.message}
required
onChange={e =>
setFormData({ ...formData, message: e.target.value })
}
/>
<FormContainerImg>
<Filebase
required
type="file"
multiple={false}
onDone={({ base64 }) =>
setFormData({ ...formData, image: base64 })
}
/>
</FormContainerImg>
<FormContainerButtons>
<Buttons type="submit" create>
{specificPost ? "Edit" : "Create"}
</Buttons>
<Buttons onClick={clear} clear>
Clear
</Buttons>
</FormContainerButtons>
</Data>
</FormContainer>
</Wrapper>
);
};
export default Form;
My actions
import {
GETPOSTS,
CREATEPOST,
DELETEPOST,
UPDATEPOST,
LIKEPOST
} from "../actionTypes/posts.js";
import * as api from "../api/posts.js";
export const getPosts = () => async dispatch => {
try {
const { data } = await api.getPosts();
dispatch({ type: GETPOSTS, payload: data });
} catch (error) {
console.log(error);
}
};
export const createPost = newPost => async dispatch => {
try {
const { data } = await api.createPost(newPost);
dispatch({ type: CREATEPOST, payload: data });
} catch (error) {
console.log(error);
}
};
export const updatePost = (id, updatePost) => async dispatch => {
try {
const { data } = await api.updatePost(id, updatePost);
dispatch({ type: UPDATEPOST, payload: data });
} catch (error) {
console.log(error);
}
};
export const deletePost = id => async dispatch => {
try {
await api.deletePost(id);
dispatch({ type: DELETEPOST, payload: id });
} catch (error) {
console.log(error);
}
};
Redux Part
import {
GETPOSTS,
CREATEPOST,
DELETEPOST,
UPDATEPOST,
LIKEPOST
} from "../actionTypes/posts.js";
const postData = (posts = [], action) => {
switch (action.type) {
case GETPOSTS:
return action.payload;
case CREATEPOST:
return [...posts, action.payload];
case UPDATEPOST:
return posts.map(post =>
action.payload._id === post._id ? action.payload : posts
);
case DELETEPOST:
return posts.filter(post => post._id !== action.payload);
default:
return posts;
}
};
export default postData;
My controllers in the backend
import mongoose from "mongoose";
import infoPost from "../models/posts.js";
// Getting All The Posts
export const getPosts = async (req, res) => {
try {
const Posts = await infoPost.find();
res.status(200).json(Posts);
} catch (error) {
res.status(404).json({ message: error.message });
console.log(error);
}
};
// Creating A Post
export const createPost = async (req, res) => {
const { title, message, image } = req.body;
const newPost = new infoPost({ title, message, image });
try {
await newPost.save();
res.status(201).json(newPost);
} catch (error) {
res.status(409).json({ message: error.message });
console.log(error);
}
};
// Update A Post
export const updatePost = async (req, res) => {
const { id } = req.params;
const { title, message, image } = req.body;
if (!mongoose.Types.ObjectId.isValid(id))
return res.status(404).send(`No Post With Id Of ${id}`);
const updatedPost = { title, message, image, _id: id };
await infoPost.findByIdAndUpdate(id, updatedPost, { new: true });
res.json(updatedPost);
};
// Deleting A Post
export const deletePost = async (req, res) => {
const { id } = req.params;
if (!mongoose.Types.ObjectId.isValid(id))
return res
.status(404)
.send(`We Couldnt Found The Post With Id Of ${id} To Delete`);
await infoPost.findByIdAndRemove(id);
res.json(`Post With Id Of ${id} Deleted Succesfully`);
};
// Liking A Post
export const likePost = async (req, res) => {
const { id } = req.params;
if (!mongoose.Types.ObjectId.isValid(id))
return res.status(404).send(`No post with id: ${id}`);
const post = await infoPost.findById(id);
const updatedPost = await infoPost.findByIdAndUpdate(
id,
{ likeCount: post.likeCount + 1 },
{ new: true }
);
res.json(updatedPost);
};
Even though i've been trying to solve this problem for nearly 3.5 hours, i think that the problem might be in my Posts.js part, if you can help me, you're the greatest !

react-redus post api call err 404 not found

Hello today I started working with redux so I am a beginner and I want to make my register request the API Is working perfectly I tested it with postman and also with normal fetch on a component without redux and worked so API is not the problem.
Basically, I want to send user data and get the token back I get 404 not found error in the console here is my code =>
import React, { useState } from 'react';
import './App.css';
import { Provider, connect } from 'react-redux'
import store from './store'
import { register } from './actions/auth'
import PropTypes from 'prop-types';
function App({ register }) {
const [username, setUsername] = useState("")
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
return (
<>
<input placeholder="email" onChange={(e) => { setEmail(e.target.value) }} />
<input placeholder="username" onChange={(e) => { setUsername(e.target.value) }} />
<input placeholder="password" onChange={(e) => { setPassword(e.target.value) }} />
<button onClick={() => { register({ username, password, email }) }}>register</button>
</>
);
}
//todo proptypes
register.PropTypes = {
register: PropTypes.func.isRequired
}
export default connect(null, { register })(App);
// import
import axios from 'axios'
import { REGISTER_FAIL, REGISTER_SUCCESS } from './types'
//register user
export const register = ({ name, email, password }) => async dispatch => {
const config = {
headers: {
"Content-Type": "application/json"
}
}
const body = JSON.stringify({ name, email, password })
try {
const res = await axios.post('http://localhost:3000/api/register', body, config);
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
})
} catch (error) {
dispatch({
type: REGISTER_FAIL
})
}
}
import { REGISTER_FAIL, REGISTER_SUCCESS } from '../actions/types'
const initialState = {
token: localStorage.getItem("token"),
isAuthenticated: null,
user: null
}
export default function (state = initialState, action) {
const { type, payload } = action
switch (type) {
case REGISTER_SUCCESS:
localStorage.setItem("token", payload.token);
return {
...state,
...payload,
isAuthenticated: true
}
case REGISTER_FAIL:
localStorage.removeItem("token");
return {
...state,
token: null,
isAuthenticated: false
};
default:
return state
}
}

Resources