Андрій
Привет, кто-то может подсказать как сделать обновление state в redux сразу после request? Кода много, чтобы его бросать, потому в краткости опишу как всё у меня работает. У меня есть форма регистрации в которой я проверяю существует ли этот юзер в базе данных. Отправляю запрос в апи,после получаю данные и записываю их в state. Но когда получаю данные со state, то они ещё не обновились. Если нужен будет код, то скину. Использовал componentDidUpdate и use effect, но ничего не помогло. Заранее спасибо за помощь!
Kalebra
может ты стейт не правильно меняешь?
Kalebra
не через setState
Koks
Проверь точно меняешь стейт
Kalebra
ты его должен получать в компонент через mapStateToProps
Андрій
Он точно меняется
Kalebra
а менять через mapDispatchToProps
Андрій
Но только после окончания цыкла
Koks
Он точно меняется
Стор сам оповещает компоненты
Андрій
import { AuthAPI } from '../api/api'; const TOGGLE_IS_STATUS = 'TOGGLE_IS_STATUS'; const TOGGLE_IS_CONFIRM_PASSWORD = 'TOGGLE_IS_CONFIRM_PASSWORD'; const GET_LOGIN = 'GET_LOGIN'; const SET_PASSWORD = 'SET_PASSWORD'; const SET_CONFIRM_PASSWORD = 'SET_CONFIRM_PASSWORD'; export const toggleIsStatus = status => ({ type: TOGGLE_IS_STATUS, status: status, }); export const getLogin = login => ({ type: GET_LOGIN, login: login, }); export const toggleIsConfirmPassword = (pass1, pass2) => ({ type: TOGGLE_IS_CONFIRM_PASSWORD, pass1: pass1, pass2: pass2, }); let initialState = { status: null, isStatus: false, login: null, isConfirmPassword: false, password: null, }; const RegisterReducer = (state = initialState, action) => { switch (action.type) { case TOGGLE_IS_STATUS: return { ...state, isStatus: action.status === 'Exists' ? true : false, // login:action.status, }; case GET_LOGIN: return { ...state, login: action.login, }; case TOGGLE_IS_CONFIRM_PASSWORD: return { ...state, isConfirmPassword: action.pass1 == action.pass2 ? true : false, }; default: return state; } }; export const getStatus = login => { return dispatch => { AuthAPI.getStatus(login).then(request => { dispatch(toggleIsStatus(request.data)); console.log('real -> '+request.data); }); }; }; export const registerForm = data => { return () => { AuthAPI.registerForm(data).then(response => { console.log('Registered' + response); }); }; }; export default RegisterReducer;
Kalebra
в реакт вшит автоматический рендеринг если юзать setState
Kalebra
Kalebra
что за стрелка в ретурн?
Андрій
export const getStatus = login => { return dispatch => { AuthAPI.getStatus(login).then(request => { dispatch(toggleIsStatus(request.data)); console.log('real -> '+request.data); }); }; };
Андрій
это проверяет
Koks
Тут не происходит записи в стор
Kalebra
это ошибка. так писать нельзя
Андрій
это совсем другой хук
Kalebra
это не компонента а обычная функция ведь
Kalebra
Kalebra
диспач который вызывает внутри себя диспач
Kalebra
это нужно через thunk делать
Андрій
так это ж и есть она
Koks
Это она и есть)
Андрій
const instance = axios.create({ baseURL: 'http://127.0.0.1:5000/', }); export const AuthAPI = { getStatus(login) { return instance.get(users/checkUser, { params: { username: login } }).then(request => { return request; }); }, вот мой запрос
Андрій
потом переходит в санку
Андрій
import React from 'react'; import Register from '.'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { compose } from 'redux'; import { getStatus, getLogin, registerForm, toggleIsConfirmPassword, } from '../../redux/registerReducer'; class RegisterContainer extends React.Component { // componentDidUpdate() { // this.props.getStatus(this.props.login); // console.log(this.props.login); // } render() { return <Register {...this.props} />; } } let mapStateToProps = state => ({ isStatus: state.register.isStatus, login: state.register.login, isConfirmPassword: state.register.isConfirmPassword, RegisterForm: state.form.RegisterForm, }); export default compose( connect( mapStateToProps, { getStatus, getLogin, registerForm, toggleIsConfirmPassword }, ), )(RegisterContainer);
Андрій
потом мой контейнер
Андрій
import React from 'react'; import { useState,useEffect,useLayoutEffect } from 'react'; import s from './index.module.css'; import Form from 'react-bootstrap/Form'; import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import InputGroup from 'react-bootstrap/InputGroup'; import FormControl from 'react-bootstrap/FormControl'; import ButtonDefault from '../buttonDefault'; import { Field, reduxForm } from 'redux-form'; import { InputText, InputEmail, InputPassword } from '../common/formsControls'; import { required, maxLengthCreator, email, minLengthCreator, checkLengthPesel, checkNumbers, isLoginCreator, isConfirmCreator, } from '../../utils/validation'; import * as axios from 'axios'; class Register extends React.Component { state = { password: null, isConfirm: undefined, }; postData = data => { this.props.registerForm(data); }; isConfirm = isConfirmCreator(this.state.password, this.state.confirmPassword); isLogin = isLoginCreator(this.props.isStatus); render() { return ( <div className={s.backgroundRegister}> <div className={s.container}> <RegisterFormRedux login={this.props.login} onSubmit={this.postData} isLogin={this.isLogin} getStatus={this.props.getStatus} password={this.state.password} isStatus = {this.props.isStatus} isConfirmPasswordError={this.isConfirmPasswordError} isConfirm={this.isConfirm} getLogin={this.props.getLogin} /> <div className={s.infoContainer}> <div className={s.info}> <span className={s.textInfo}>Do you have an account?</span> <div className={s.buttonLinkLogin}> <ButtonDefault to="/login" buttonName="login" /> </div> </div> </div> </div> </div> ); } } const maxLength15 = maxLengthCreator(15); const minLength6 = minLengthCreator(6); const FormRegister = props => { let [isStatus, setStatus] = useState(props.isStatus); useEffect(()=>{ setStatus(props.isStatus); },[props.isStatus]); let [login, setLogin] = useState(props.login); useLayoutEffect(()=>{ setLogin(props.login); },[props.login]); const onBlurLoginInput = values => { props.getStatus(values.currentTarget.defaultValue); console.log(isStatus); console.log('show -> '+login); //props.getLogin(values.currentTarget.defaultValue); };
Андрій
return ( <Form className={s.formRegister} onSubmit={props.handleSubmit}> <Form.Group as={Row} controlId="formBasicFirstName"> <Form.Label column sm="4"> First Name </Form.Label> <Col sm="7"> <Field name="firstName" placeholder="First Name" validate={[required, maxLength15]} component={InputText} /> </Col> </Form.Group> <Form.Group as={Row} controlId="formBasicSecondName"> <Form.Label column sm="4"> Second Name </Form.Label> <Col sm="7"> <Field name="secondName" placeholder="Second Name" validate={[required, maxLength15]} component={InputText} /> </Col> </Form.Group> <Form.Group as={Row} controlId="formBasicEmail"> <Form.Label column sm="4"> Email </Form.Label> <Col sm="7"> <Field name="email" placeholder="Email" validate={[required, maxLength15, email]} component={InputEmail} /> </Col> </Form.Group> <Form.Group as={Row} controlId="formBasicEmail"> <Form.Label column sm="4"> Login </Form.Label> <Col sm="7"> <Field name="login" placeholder="Login" validate={[required, maxLength15, props.isLogin]} component={InputEmail} type="login" onBlur={onBlurLoginInput} /> </Col> </Form.Group> <Form.Group as={Row} controlId="formBasicPassword"> <Form.Label column sm="4"> Password </Form.Label> <Col sm="7"> <Field name="password" placeholder="Password" validate={[required, maxLength15, minLength6]} component={InputPassword} /> </Col> </Form.Group> {/* <Form.Group as={Row} controlId="formBasicConfirmPassword"> <Form.Label column sm="4"> Confirm Password </Form.Label> <Col sm="7"> <Field name="confirmPassword" placeholder="Confirm Password" validate={[required, maxLength15, minLength6, props.isConfirm]} component={InputPassword} /> </Col> </Form.Group> <Form.Group as={Row} controlId="formBasicRadio"> <Form.Label column sm="4"> Gender </Form.Label> <Col sm="2"> <div className={s.checkboxContainer}> <label className={s.checkboxLabel}> <Field component={'input'} type="radio" name="gender" value="M" /> <span className={s.checkboxCustomRectangular}></span> </label> <div className={s.inputTitle}>Male</div> </div> </Col> <Col sm="2"> <div className={s.checkboxContainer}> <label className={s.checkboxLabel}> <Field component= {'input'} type="radio" name="gender" value="F" /> <span className={s.checkboxCustomRectangular}></span> </label> <div className={s.inputTitle}>Female</div> </div> </Col> <Col sm="2"></Col> </Form.Group> <Form.Group as={Row} controlId="formBasicDate"> <Form.Label column sm="4"> Date of Birth </Form.Label> <Col sm="7"> <Field type="date" className={s.dateRegister} component={Form.Control} name="date" /> </Col> </Form.Group> */} {/* <Form.Group as={Row} controlId="formBasicText"> <Form.Label column sm="4"> PESEL </Form.Label> <Col sm="7"> <Field name="pesel" placeholder="PESEL" validate={[required, checkLengthPesel]} component={InputText} /> </Col> </Form.Group> */} {/* <Form.Group as={Row} controlId="formBasicText">
Андрій
<Form.Label column sm="4"> File </Form.Label> <Col sm="7"> <Field type="file" className={s.customFileInput} component={Form.Control} name="file" /> </Col> </Form.Group> */} <div className={s.formButton}> <button className={s.buttonRegister}>Register</button> </div> </Form> ); }; const RegisterFormRedux = reduxForm({ form: 'RegisterForm' })(FormRegister); export default Register;
Андрій
а это уже сам компонент
Koks
Омагад) у меня тут все сложно
Koks
С телефона😂
Kalebra
ты должен диспачить объект с полем type
Koks
Санка где?)
Kalebra
а у тебя в коде диспач шото нереальное делает
Kalebra
вот пример
Андрій
а у тебя в коде диспач шото нереальное делает
всё он отлично делает) проблема же в другом. Что мне нужно получить данные сразу после запроса, чтобы сделать валидацию формы
Андрій
const onBlurLoginInput = values => { props.getStatus(values.currentTarget.defaultValue); console.log(isStatus); console.log('show -> '+login); //props.getLogin(values.currentTarget.defaultValue); };
Андрій
санка здесь))
Koks
вот пример
Тут ошибочка вышла)))
Koks
Это чье?
Koks
Await нужен перед обращением к АПИ
Kalebra
ошибочка? где?
Koks
ошибочка? где?
Там где const data = await и дальше
Kalebra
lol да)
Андрій
вот моя фома, здесь происходит валидация логина или он сущестувет. После забирания фокуса отправляю запрос и проверяю
Koks
Это чей код то был?)
Андрій
const onBlurLoginInput = values => { props.getStatus(values.currentTarget.defaultValue); console.log(isStatus); console.log('show -> '+login); //props.getLogin(values.currentTarget.defaultValue); };
Андрій
вот сайнка
Андрій
тут санку использую
Андрій
export const getStatus = login => { return dispatch => { AuthAPI.getStatus(login).then(request => { dispatch(toggleIsStatus(request.data)); console.log('real -> '+request.data); }); }; };
Андрій
вот сама санта
Koks
Первое не санка
Андрій
я знаю
Андрій
второе санта
Koks
И что в логах?)
Koks
Выводит в консоль?
Андрій
ну я пока для проверки на колсоль вывожу, чтобы смотреть, что приходит в санку и что в сомпонент
Koks
Ну так в консоль выводит данные?
Koks
В Санке есть консол.лог он выводит данные?
Андрій
последние 3 строки в консоли
Андрій
в санке он вывод правильное
Андрій
а в компоненте нет
Андрій
потому что редакс ещё не передал новые данные в компонент
Андрій
проблема до конца понятна?) или ещё обьяснить?)
Koks
Я ищю редьюсер)
Koks
Хаха
Андрій
import { AuthAPI } from '../api/api'; const TOGGLE_IS_STATUS = 'TOGGLE_IS_STATUS'; const TOGGLE_IS_CONFIRM_PASSWORD = 'TOGGLE_IS_CONFIRM_PASSWORD'; const GET_LOGIN = 'GET_LOGIN'; const SET_PASSWORD = 'SET_PASSWORD'; const SET_CONFIRM_PASSWORD = 'SET_CONFIRM_PASSWORD'; export const toggleIsStatus = status => ({ type: TOGGLE_IS_STATUS, status: status, }); export const getLogin = login => ({ type: GET_LOGIN, login: login, }); export const toggleIsConfirmPassword = (pass1, pass2) => ({ type: TOGGLE_IS_CONFIRM_PASSWORD, pass1: pass1, pass2: pass2, }); let initialState = { status: null, isStatus: false, login: null, isConfirmPassword: false, password: null, }; const RegisterReducer = (state = initialState, action) => { switch (action.type) { case TOGGLE_IS_STATUS: return { ...state, isStatus: action.status === 'Exists' ? true : false, login:action.status, }; case GET_LOGIN: return { ...state, login: action.login, }; case TOGGLE_IS_CONFIRM_PASSWORD: return { ...state, isConfirmPassword: action.pass1 == action.pass2 ? true : false, }; default: return state; } }; export const getStatus = login => { return dispatch => { AuthAPI.getStatus(login).then(request => { dispatch(toggleIsStatus(request.data)); console.log('real -> '+request.data); }); }; }; export const registerForm = data => { return () => { AuthAPI.registerForm(data).then(response => { console.log('Registered' + response); }); }; }; export default RegisterReducer;
Андрій
вот
Koks
О
Андрій
О
ты знаешь как правильно использовать useEffect, чтобы данные обновились в компоненте сразу после обновления их в redux