У меня есть приложение, созданное с помощью Rails, React и Webpacker. Я использую аутентификацию на основе токенов, поэтому, когда пользователь создает учетную запись или выполняет вход, ему назначается токен в БД. Этот токен затем используется для доступа к профилю пользователя. Страница профиля загружается без проблем после аутентификации пользователя, но я получаю сообщение об ошибке Rails, говорящее Couldn't find Registration
, и затем оно ссылается на эту строку из моего registration_controller: registration = Registration.find_by_auth_token!(request.headers[:token])
.
Я попытался установить токен в localStorage, когда он получен из бэкэнда, и я попытался вызвать токен из localStorage, когда страница загружается на компоненты верхнего уровня, используя хук useEffect
, но этоне похоже, что мое приложение React даже начинает рендериться, пока я не получил эту страницу с ошибкой. Ни одно из утверждений Console.log, которые я добавил в свое приложение React, не появляется в консоли, когда я получаю эту ошибку.
registration_controller.rb
class RegistrationController < ApplicationController
skip_before_action :verify_authenticity_token
def index; end
def custom
user = Registration.create!(registration_params)
render json: { token: user.auth_token, id: user.id }
end
def profile
registration = Registration.find_by_auth_token!(request.headers[:token])
render json: {
registration: { username: registration.username, email: registration.email, name: registration.name }
}
end
private
def registration_params
params.require(:registration).permit(:username, :email, :password, :name)
end
end
auth.js (действия)
import axios from 'axios';
import reduxStore from '../reduxStore';
export const LOGOUT_START = 'auth/logoutStart';
export const LOGOUT_SUCCESSFUL = 'auth/logoutSuccessful';
export const LOGOUT_ERROR = 'auth/logoutError';
export const LOGIN_START = 'auth/loginStart';
export const LOGIN_SUCCESSFUL = 'auth/loginSuccessful';
export const LOGIN_FAILURE = 'auth/loginFailure';
export const REGISTRATION_START = 'auth/registrationStart';
export const REGISTRATION_SUCCESSFUL = 'auth/registrationSuccessful';
export const REGISTRATION_FAILURE = 'auth/registrationFailure';
export const logout = () => (dispatch) => {
const headers = { token: localStorage.token };
// console.log('redux store', reduxStore().getState())
// console.log('NEW local storage', localStorage);
dispatch({ type: LOGOUT_START });
try {
axios.delete('/logout', { headers })
.then((res) => {
dispatch({
type: LOGOUT_SUCCESSFUL,
payload: res.data,
});
});
} catch (e) {
console.error(`logout error: ${e}`);
dispatch({
type: LOGOUT_ERROR,
payload: e,
});
}
};
export const login = ({ username, password }) => (dispatch) => {
const headers = {
'Content-Type': 'application/json',
};
const data = {
username,
password,
};
dispatch({ type: LOGIN_START });
try {
axios.post('/login', data, { headers })
.then((res) => {
localStorage.setItem('token', res.data.token);
dispatch({
type: LOGIN_SUCCESSFUL,
payload: res.data,
});
// localStorage.setItem('myValueInLocalStorage', event.target.value)
console.log('localStorage', localStorage);
});
} catch (e) {
console.error(`login error ${e}`);
dispatch({
type: LOGIN_FAILURE,
payload: e,
});
}
};
export const createUser = ({
username,
password,
name,
email,
}) => (dispatch) => {
const headers = {
'Content-Type': 'application/json',
};
const data = {
registration: {
username,
password,
name,
email,
},
};
dispatch({ type: REGISTRATION_START });
try {
axios.post('/registration/custom', data, { headers })
.then((res) => {
dispatch({
type: REGISTRATION_SUCCESSFUL,
payload: res.data,
});
});
} catch (e) {
console.error(`createUser error: ${e}`);
dispatch({
type: REGISTRATION_FAILURE,
payload: e,
});
}
};
Я ожидаю, что этот токен будет всегда доступен из заголовков объекта Request на стороне Rails, поэтому страница профиля может отображаться, когда пользователь обновляет окно.