Почему атрибут value отображает входные данные как только для чтения, а defaultValue - как для чтения и записи?

Итак, у меня есть корзина, в которой количество добавленных товаров динамически увеличивается на +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} &times; {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, затем щелкните магазин, затем щелкните корзину, затем добавьте в корзину несколько экземпляров того же товара, затем перейдите в корзину и попробуйте и вручную изменить значение элемента.

Не могли бы вы поделиться реализацией handleChangeEvent?

Kabbany 11.01.2019 16:01

Также carItem не определен во фрагменте, верно?

Kabbany 11.01.2019 16:03

Можем ли мы увидеть вашу функцию this.handleChangeEvent?

Treycos 11.01.2019 16:04

@Kabbany @Treycos Я изменил свой вопрос, чтобы показать handleChangeEvent. Что касается cartItem, который передается как опора const { cartItem, client } = this.props

TheoG 11.01.2019 16:06

carItem - это состояние или подпорка?

Kabbany 11.01.2019 16:08

@Kabbany cartItem - это опора.

TheoG 11.01.2019 16:08
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
6
52
3

Ответы 3

Я думаю, проблема в том, что вы передаете значение из props carItem в defaultValue, но onChange вы меняете состояние, которое не передается в defaultValue.

Чтобы исправить это, вам нужно передать состояние defaultValue ИЛИ обновить опору carItem в onChange

Первая проблема заключается в том, что defaultValue устанавливается только при начальной загрузке формы. После этого он не будет обновляться «естественным образом», потому что целью было только установить начальное значение по умолчанию. Состояние правильно передается в value, как видно из консоли разработчика, но что бы я ни делал, это поле не редактируется, так как оно остается только для чтения. Если вы перейдете сюда: flamingo-next-production.herokuapp.com, войдите в систему с помощью [email protected] и testing123, затем щелкните магазин, затем щелкните корзину, затем добавьте в корзину, кратные одному и тому же элементу, затем перейдите в корзину и попробуйте вручную изменить элемент. ценность

TheoG 11.01.2019 21:05

Похоже, вы делаете управляемый ввод со значением по умолчанию из состояния? Если это так, вам нужно будет установить начальное количество в состоянии на значение 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 на любое другое значение, это не позволит мне

TheoG 11.01.2019 16:51

Это заставляет меня думать, что значение количества в вашем состоянии не обновляется должным образом. Используете ли вы количество из вашего штата в опоре стоимости?

Chris 11.01.2019 17:10

Если вы перейдете сюда: https://flamingo-next-production.herokuapp.com и войдете в систему с помощью [email protected] и testing123, затем щелкните shop, затем щелкните, откройте корзину, затем add to cart элемент, затем снова добавьте этот же элемент, затем войдите в корзину и попробуйте вручную изменить отображаемое значение.

TheoG 11.01.2019 17:37

Да, если вы проверите состояние и свойства, вы увидите, что состояние действительно обновляется. Я также вижу, что вы все еще используете quantity из опоры cartItem.

Chris 11.01.2019 17:43

К сожалению, ваше решение не решает мою проблему. Я изменил свой исходный вопрос полным кодом. Все работает отлично, поле просто не выходит из режима только для чтения и, таким образом, не позволяет мне вручную обновить его с новым значением.

TheoG 11.01.2019 21:20

Проблема была решена путем удаления 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
            }}
        );       
    }

Другие вопросы по теме