Итак, у меня есть корзина, в которой количество добавленных товаров динамически увеличивается на +1 каждый раз, когда вы добавляете тот же товар, а внутри самой корзины количество добавленных товаров можно вручную изменить с помощью любого предпочтительного номера пользователя.
Если я использую атрибут value = "" в поле ввода, значение динамически обновляется правильно, но не позволяет мне вручную изменять значение. И если я использую defaultValue = "", значение не обновляется правильно каждый раз при добавлении элемента, но позволяет мне вручную изменять значение по мере необходимости.
Как я могу правильно показать динамическое значение и иметь возможность обновлять поле значения по мере необходимости? Мой код выглядит следующим образом:
class CartItem2 extends Component {
constructor(props) {
super(props);
}
handleChangeEvent = e => {
const { name, type, value } = e.target;
const val = type === 'number' ? parseFloat(value) : value;
this.setState(() => { return { [name]: val }});
};
updateCartItem = async (e, updateCartItemMutation) => {
e.preventDefault();
console.info('Updating Cart Item!!');
console.info(this.state);
const res = await updateCartItemMutation({
variables: {
id: this.props.cartItem.id,
quantity: this.state.quantity,
},
});
console.info('Updated!!');
};
static getDerivedStateFromProps(nextProps, prevState){
if (nextProps.cartItem.quantity !== prevState.quantity) {
console.info("nextProps ", nextProps);
console.info("prevState", prevState);
return {quantity: nextProps.cartItem.quantity};
}
else return null;
}
render() {
const { cartItem, client } = this.props;
const { quantity } = this.state;
return (
<CartItemStyles>
<img width = "100" src = {cartItem.item.image} alt = {cartItem.item.title} />
<div className = "cart-item-details">
<h3>{cartItem.item.title}</h3>
<p>
{formatMoney(cartItem.item.price * cartItem.quantity)}
{' - '}
<em>
{cartItem.quantity} × {formatMoney(cartItem.item.price)} each
</em>
</p>
<Mutation
mutation = {UPDATE_CART_ITEM_MUTATION}
variables = {this.state}
>
{(updateCartItem, { loading, error }) => {
return (
<Form2 key = {cartItem.id} onSubmit = {e => this.updateCartItem(e, updateCartItem)}>
<Error error = {error} />
<label htmlFor = "quantity">
<input
type = "number"
id = "quantity"
name = "quantity"
placeholder = "Quantity"
required
value = {quantity}
onChange = {this.handleChangeEvent}
/>
</label>
<button type = "submit">Updat{loading ? 'ing' : 'e'}</button>
</Form2>
)
}}
</Mutation>
</div>
<RemoveFromCart id = {cartItem.id} />
</CartItemStyles>
);
}
}Если вы перейдете сюда: flamingo-next-production.herokuapp.com, войдите в систему с помощью [email protected] и testing123, затем щелкните магазин, затем щелкните корзину, затем добавьте в корзину несколько экземпляров того же товара, затем перейдите в корзину и попробуйте и вручную изменить значение элемента.
Также carItem не определен во фрагменте, верно?
Можем ли мы увидеть вашу функцию this.handleChangeEvent?
@Kabbany @Treycos Я изменил свой вопрос, чтобы показать handleChangeEvent. Что касается cartItem, который передается как опора const { cartItem, client } = this.props
carItem - это состояние или подпорка?
@Kabbany cartItem - это опора.






Я думаю, проблема в том, что вы передаете значение из props carItem в defaultValue, но onChange вы меняете состояние, которое не передается в defaultValue.
Чтобы исправить это, вам нужно передать состояние defaultValue ИЛИ обновить опору carItem в onChange
Первая проблема заключается в том, что defaultValue устанавливается только при начальной загрузке формы. После этого он не будет обновляться «естественным образом», потому что целью было только установить начальное значение по умолчанию. Состояние правильно передается в value, как видно из консоли разработчика, но что бы я ни делал, это поле не редактируется, так как оно остается только для чтения. Если вы перейдете сюда: flamingo-next-production.herokuapp.com, войдите в систему с помощью [email protected] и testing123, затем щелкните магазин, затем щелкните корзину, затем добавьте в корзину, кратные одному и тому же элементу, затем перейдите в корзину и попробуйте вручную изменить элемент. ценность
Похоже, вы делаете управляемый ввод со значением по умолчанию из состояния? Если это так, вам нужно будет установить начальное количество в состоянии на значение cartItem.quantity.
Многие ссылки отсутствуют ниже, но вы должны уловить идею.
class CartItem extends Component {
constructor(props) {
super(props);
this.state = {
quantity: props.cartItem.quantity,
};
}
handleChangeEvent = e => {
const { name, type, value } = e.target;
const val = type === 'number' ? parseFloat(value) : value;
this.setState({ [name]: val });
};
render() {
const { quantity } = this.state;
return (
<Mutation
mutation = {UPDATE_CART_ITEM_MUTATION}
variables = {this.state}
>
{(updateCartItem, { loading, error }) => {
return (
<Form2 onSubmit = {e => this.updateCartItem(e, updateCartItem)}>
<Error error = {error} />
<label htmlFor = "quantity">
<input
type = "number"
id = "quantity"
name = "quantity"
placeholder = "Quantity"
value = {quantity}
onChange = {this.handleChangeEvent}
required
/>
</label>
<button type = "submit">Updat{loading ? 'ing' : 'e'}</button>
</Form2>
)
}}
</Mutation>
)
}
}
Текущее значение количества отображается правильно при использовании value=, но если я попытаюсь вручную изменить значение поля ввода на что-то другое впоследствии, я не смогу. Поле остается доступным только для чтения. Итак, я добавил элемент 5 раз, и в поле ввода отображается 5, если я попытаюсь изменить 5 на любое другое значение, это не позволит мне
Это заставляет меня думать, что значение количества в вашем состоянии не обновляется должным образом. Используете ли вы количество из вашего штата в опоре стоимости?
Если вы перейдете сюда: https://flamingo-next-production.herokuapp.com и войдете в систему с помощью [email protected] и testing123, затем щелкните shop, затем щелкните, откройте корзину, затем add to cart элемент, затем снова добавьте этот же элемент, затем войдите в корзину и попробуйте вручную изменить отображаемое значение.
Да, если вы проверите состояние и свойства, вы увидите, что состояние действительно обновляется. Я также вижу, что вы все еще используете quantity из опоры cartItem.
К сожалению, ваше решение не решает мою проблему. Я изменил свой исходный вопрос полным кодом. Все работает отлично, поле просто не выходит из режима только для чтения и, таким образом, не позволяет мне вручную обновить его с новым значением.
Проблема была решена путем удаления static getDerivedStateFromProps() и замены на:
componentDidUpdate(prevProps, prevState) {
if (this.props.cartItem.quantity !== prevProps.cartItem.quantity) {
let quantity = this.props.cartItem.quantity;
this.setState(() => {
return {
quantity
}}
);
}
}
componentDidMount() {
let quantity = this.props.cartItem.quantity;
this.setState(() => {
return {
quantity
}}
);
}
Не могли бы вы поделиться реализацией
handleChangeEvent?