Im using JWT with a Rails backend/React frontend. Im attempting to have my user redirected when they log into their account to the /home page of the site. The error I am receiving is
TypeError: Cannot read property 'push' of undefined
Login.<anonymous>
src/components/Login.js:20
17 | if(res.user){
18 | localStorage.token = res.token
19 | this.setState({user:{id:res.user.id, username:res.user.username, token:res.token}, home:res.user.home}, () => {
> 20 | this.props.history.push('/home')
| ^ 21 | })
22 | } else {
23 | alert(res.error)
Ive did make a change, to the home component but since reverted back to what it was but still having issues....
my controllers...
class ApplicationController < ActionController::API
def encode_token(payload)
JWT.encode(payload, "coffee")
end
def auth_header
# { Authorization: 'Bearer <token>' }
request.headers['Authorization']
end
def decoded_token
if auth_header
token = auth_header.split(' ')[1]
# header: { 'Authorization': 'Bearer <token>' }
begin
JWT.decode(token,'coffee', true, algorithm: 'HS256')
rescue JWT::DecodeError
nil
end
end
end
def current_user
if decoded_token
user_id = decoded_token[0]['user_id']
@user = User.find_by(id: user_id)
end
end
def logged_in?
!!current_user
end
def authorized
render json: { message: 'Please log in' }, status: :unauthorized unless logged_in?
end
end
----
class UsersController < ApplicationController
before_action :authorized, only:[:persist]
def create
@user = User.create(user_params)
if @user.valid?
token = encode_token({user_id: @user.id})
render json: @user
else
render json: {error:'failed to create a user'}
end
end
def login
@user = User.find_by(username:params[:username])
if @user && @user.authenticate(params[:password])
token = encode_token({user_id: @user.id})
render json: {user:UserSerializer.new(@user), token:token}
else
render json: {error:"wrong user or password"}
end
end
def index
@user = User.all
render json: @user
end
def persist
token = encode_token({user_id: @user.id})
render json: {user:UserSerializer.new(@user), token:token}
end
private
def user_params
params.permit(:username, :password)
end
end
my user_serializer...
class UserSerializer < ActiveModel::Serializer
attributes :id, :username
has_many :favorites
has_many :favorite_coffee_shops, through: :favorites, source: :coffee_shop
has_many :reviews
has_many :coffee_shops, through: :reviews
end
my login component...
import React from 'react';
import SignUp from './SignUp';
class Login extends React.Component{
state={
user:{
id:0,
username:"",
token:""
},
home:[]
}
handleAuthResponse = (res) => {
if(res.user){
localStorage.token = res.token
this.setState({user:{id:res.user.id, username:res.user.username, token:res.token}, home:res.user.home}, () => {
this.props.history.push('/home')
})
} else {
alert(res.error)
}
}
handleLogin = (e, userInfo) =>{
e.preventDefault()
console.log(e)
fetch('http://localhost:3000/login',{
method:"POST",
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify(userInfo)
})
.then(res => res.json())
.then(json => {
console.log(json)
if(!json.error){
this.handleAuthResponse(json)
}else {
alert(json.error)
}
})
.catch(err => console.log(err))
}
handleChange = (e) => {
let {name, value} = e.target
this.setState({
[name]: value
})
}
render(){
return (
<div className="login">Welcome Back!
<form onSubmit={(e) => this.handleLogin(e, this.state)}>
<div>
<label>UserName</label>
<br></br>
<input type="text" name="username" value={this.state.username} onChange={this.handleChange}/>
</div>
<div>
<label>Password</label>
<br></br>
<input type="password" name="password" value={this.state.password} onChange={this.handleChange}/>
</div>
<input type="submit" value="Submit" className="sl-btn" />
</form>
<div></div>
<SignUp />
</div>
);
}
}
export default Login;
and my home component im attempting to push the user to once logged-in
import React from 'react'
import MapContainer from '../containers/MapContainer'
import NavBar from './NavBar'
import FavoritesContainer from './FavoritesContainer'
class Home extends React.Component {
state = {
reviews: [],
favorites: [],
}
componentDidMount(){
fetch('http://localhost:3000/reviews')
.then(res => res.json())
.then(reviews => this.setState({ reviews }))
}
addReview = (review) => {
fetch('http://localhost:3000/reviews',{
method: "POST",
headers: {
"Content-Type" : "application/json",
Accept: "application/json",
Authorization: `bearer ${localStorage.token}`
},
body: JSON.stringify({ review: review }
),
})
.then(res => res.json())
.then(( json => {
this.setState(prevState => ({
reviews: [...prevState.reviews, json ]
}))
}))
}
render() {
return (
<div className="home">
<NavBar />
<MapContainer />
<FavoritesContainer />
</div>
)
}
}
export default Home
I am pretty new dev, please let me know if there is anymore info needed to help diagnose the problem. any advice would be helpful, thank you!!
Aucun commentaire:
Enregistrer un commentaire