Я создаю прототип, который отображает форму входа.Событие submit запускает поиск в базе данных.Если поиск не удастся, я хочу изменить форму на а) отобразить сообщение об ошибке и б) отменить предыдущую запись для идентификатора пользователя и пароля.
Мой редуктор изменяет состояние в Redux, но я не уверенкак перевести данные обратно в состояние компонента.
Вот моя форма:
import React from 'react';
import { NavLink } from 'react-router-dom';
import { connect } from 'react-redux';
export class LoginForm extends React.Component {
constructor(props) {
super(props);
console.log("Login form props", props);
this.state = {
userName: props.user ? props.user.userName : '',
password: props.user ? props.user.password : '',
error: props.error ? props.error : ''
}
}
onUserNameChange = (event) => {
const userName = event.target.value;
this.setState(() => ({ userName }));
};
onPasswordChange = (event) => {
const password = event.target.value;
this.setState(() => ({ password }));
};
onSubmit = (event) => {
event.preventDefault();
if (!this.state.userName || !this.state.password) {
this.setState(() => ({ error: 'User name and password are required.'}));
} else {
this.setState(() => ({ error: '' }));
this.props.onSubmit({
userName: this.state.userName,
password: this.state.password
})
}
};
render() {
console.log("Login form render() this.state", this.state);
// console.log("Login form render() this.props", this.props);
return (
<div>
{this.props.error && <p>{this.props.error}</p>}
<form onSubmit={this.onSubmit}>
<input
type="text"
placeholder="User name"
autoFocus
value={this.state.userName}
onChange={this.onUserNameChange}
/>
<input
type="password"
placeholder="Password"
value={this.state.password}
onChange={this.onPasswordChange}
/>
<button>Sign In</button>
</form>
<NavLink to="/passwordRecovery" activeClassName="is-active" exact={true}>Forgot Password?</NavLink>
<NavLink to="/newUser" activeClassName="is-active">New User?</NavLink>
</div>
)
}
}
const mapStateToProps = (state) => {
console.log('in LoginForm state.authentication: ', state.authentication);
if (state.authentication.user)
{
return {
error: state.authentication.error,
userName: state.authentication.user.userName,
password: state.authentication.user.password
}
} else {
return {
error: state.authentication.error,
user: state.authentication.user
}
}
}
export default connect(mapStateToProps, undefined)(LoginForm);
Вот страница, которая отображает форму:
import React from 'react';
import { connect } from 'react-redux';
import LoginForm from './LoginForm';
import { login, resetForm } from '../actions/authentication';
export class LoginPage extends React.Component {
onSubmit = (user) => {
console.log('LoginPage onSubmit user: ', user);
console.log('props ', this.props);
this.props.login(user);
if (this.props.user) {
this.props.history.push("/userHome");
}
}
render() {
console.log("LoginPage.render()", this.props)
return (
<div>
<LoginForm
onSubmit={this.onSubmit} error={this.props.error}
/>
</div>
);
}
}
const mapDispatchToProps = (dispatch) => ({
login: (user) => dispatch(login(user)),
resetForm: () => dispatch(resetForm())
});
const mapStateToProps = (state) => {
console.log('state.authentication: ', state.authentication);
return {
error: state.authentication.error,
user: state.authentication.user
};
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginPage);
Вот редуктор:
// reducer for authentication actions
const authenticationReducerDefaultState = {
userName: '',
password: ''
};
export default (state = authenticationReducerDefaultState, action) => {
console.log('in reducer, state: ', state);
console.log('in reducer, action: ', action);
switch (action.type) {
case 'LOGIN_REQUEST':
return {
user: action.user,
error: '',
loggedIn: false,
loggingIn: true
};
case 'LOGIN_SUCCESS':
return {
user: action.user,
error: '',
loggedIn: true,
loggingIn: false
}
case 'LOGIN_FAILURE':
return {
user: authenticationReducerDefaultState,
error: action.error,
loggedIn: false,
loggingIn: false
}
case 'LOGOUT':
return {
user: authenticationReducerDefaultState,
error: '',
loggedIn: false,
loggingIn: false
};
default:
return state;
};
};
Вот действие:
import database from '../firebase/firebase';
const request = (user) => ({
type: 'LOGIN_REQUEST',
user
});
const success = (user) => ({
type: 'LOGIN_SUCCESS',
user
});
const failure = (error) => {
// console.log('failure with error ', error);
return {
type: 'LOGIN_FAILURE',
user: { userName: '', password: '' },
error
}};
export const login = (user) => {
return (dispatch) => {
const { userName, password } = user;
// console.log(`login function for ${userName} password ${password}`);
dispatch(request(user));
let matchedUser = undefined;
return database.ref(`users`).once('value').then((snapshot) => {
snapshot.forEach((childSnapshot) => {
const user = childSnapshot.val();
if (user.userName === userName &&
user.password === password) {
matchedUser = user;
};
});
return matchedUser;
}).then((matchedUser) => {
console.log('matched user', matchedUser);
if (matchedUser) {
dispatch(success(user));
} else {
// console.log('dispatching failure');
dispatch(failure(`An error occurred looking up user ID ${userName}`));
};
console.log('end of login function');
});
}
}
// action generator for logout action
export const logout = () => ({
type: 'LOGOUT'
});
Вот мой корневой редуктор:
export default () => {
// Store creation
const store = createStore(
combineReducers({
authentication: authenticationReducer
}),
composeEnhancers(applyMiddleware(thunk))
);
return store;
}
Я надеюсь, что кто-то уже был на этом пути.Заранее спасибо.