Изучаю React.js. У меня есть форма для добавления компонентов на страницу. Я делаю валидацию этой формы. При клике на кнопку Add срабатывает функция onBtnClickHandler() которая получает значения из инпутов формы и обновляет state. В каждом инпуте у меня есть атрибут name, значение этого атрибута становится ключом, value из инпута становится значением это все у меня попадает в новый state. Форма работает хорошо. Далее c помощью функции validate() я проверяю было ли что-либо введено в инпут и обновляю state. Для этого у меня есть объект objectItems, куда я записываю состояние своего инпута, nameМоегоИнпутаIsValid : true или false. Тоже все работает. У меня в objectItems есть еще свойство formIsValid, которое по умолчанию равно false. В функции validateData() я проверяю, чтобы this.state.objectItems значение всех nameМоегоИнпутаIsValid было true и хочу обновить state переписать formIsValid : true. Но стейт не обновляется, и я не понимаю почему.
import React, { Component } from 'react';
import Card from './Card';
import apiCall from '../../Api/mockedApi';
import CardsGenerator from './CardsGenerator';
class CardsContainer extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: [],
objectItems: {
genderIsValid: false,
priceIsValid: false,
titleIsValid: false,
imageUrlIsValid: false,
formIsValid: false,
},
};
this.deleteCard = this.deleteCard.bind(this);
this.onChangeInput = this.onChangeInput.bind(this);
this.onBtnClickHandler = this.onBtnClickHandler.bind(this);
this.validate = this.validate.bind(this);
this.validateData = this.validateData.bind(this);
}
componentDidMount() {
apiCall().then(
(result) => {
this.setState({
isLoaded: true,
items: result,
});
},
(error) => {
this.setState({
isLoaded: true,
error,
});
},
);
}
onChangeInput(event) {
const { name } = event.currentTarget;
const { value } = event.currentTarget;
this.setState(state => ({ objectItems: { ...state.objectItems, [name]: value, [`${name}IsValid`]: this.validate(value) } }));
}
onBtnClickHandler(e) {
e.preventDefault();
this.setState(state => ({ items: [...state.items, state.objectItems] }));
console.log(this.state.objectItems);
this.validateData();
}
validate(value) {
if (typeof value === 'string') {
return value.length > 2;
} if (typeof value === 'number') {
return value >= 0;
}
return value;
}
validateData() {
const {
genderIsValid, priceIsValid, titleIsValid, imageUrlIsValid, formIsValid,
} = this.state.objectItems;
if (genderIsValid === true && priceIsValid === true && titleIsValid && imageUrlIsValid === true) {
this.setState(() => ({ objectItems: { formIsValid: true } }));
// this.setState({objectItems:{formIsValid:true}})
}
console.log(genderIsValid, priceIsValid, titleIsValid, imageUrlIsValid, formIsValid);
}
deleteCard(e, index) {
e.preventDefault();
const { items } = this.state;
const newItems = items.filter((item, i) => i !== index);
this.setState(() => ({
items: newItems,
}));
}
render() {
const { error, isLoaded, items } = this.state;
const itemColorBorder = () => this.state.objectItems.map(
(item, index, arr) => (item === true ? 'green' : 'red'),
);
if (error) {
return <div>No cards yet</div>;
} if (!isLoaded) {
return <div>Loading...</div>;
}
return (
<React.Fragment>
{items.map(
(item, index) => <Card info={item} index={index} del={this.deleteCard} />,
)}
<CardsGenerator id="cardGenerateForm" key={9379992} add={this.onChangeInput} submit={this.onBtnClickHandler} borderColor={itemColorBorder} disabled={this.state.objectItems.formIsValid} validate={this.validate} />
</React.Fragment>
);
}
}
export default CardsContainer;
Код в стиле
this.setState({value});
console.log(this.state.value);
не даст желаемого результата, потому что setState()
- это асинхронная операция.
Для того чтоб выполнить какой-то код после установки состояния компонента, можно передать callback вторым параметром:
this.setState({value}, () => {
// вот тут state уже находится в нужном состоянии
console.log(this.state.value);
});
В случае кода из вашего примера это будет как-то так:
this.setState(state => ({ items: [...state.items, state.objectItems] }), () => {
console.log(this.state.objectItems);
this.validateData();
});
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском
У меня есть координаты границы региона Москвы, и мне необходимо равномерно распределить точки по этому и региону и узнать их координатыЕсть...
Как сделать чтобы баннер выравнивался по центру, а не с левой стороныИспользую CMS Xenforo 2
Как сделать подобие подсветки синтаксиса?