0

I am creating a form in my App and need to add a quantity field in it. I have added a <Text> component from informed to add quantity field and used buttons to add increment and decrement feature.

But I am not able to set Text component value on button click. It seems like I can only set initialValue for <Text> component.

import React, { Component } from 'react';
import { arrayOf, number, shape, string } from 'prop-types';

import classify from 'src/classify';
import defaultClasses from './quantity.css';
import { Text } from 'informed';

class Quantity extends Component {
    static propTypes = {
        classes: shape({
            root: string,
            increment_button: string,
            decrement_button: string,
            quantity_input: string
        }),
        items: arrayOf(
            shape({
                value: number
            })
        )
    };

    state = {
        quantity: 1,
        show: true,
        max: 9999,
        min: 1
    };

    incrementQty = () => {
        this.setState(prevState => {
            if(prevState.quantity < this.state.max) {
                return {
                    quantity: parseInt(prevState.quantity) + 1
                }
            } else {
                return null;
            }
        });
        /*this.setState({ quantity: parseInt(this.state.quantity) + 1 });*/
    };
    decrementQty = () => {
        this.setState(prevState => {
            if(prevState.quantity > this.state.min) {
                return {
                    quantity: parseInt(prevState.quantity) - 1
                }
            } else {
                return null;
            }
        });
        /*this.setState({ quantity: parseInt(this.state.quantity) - 1 });*/
    };
    setQuantity = quantity => this.setState({ quantity });
    handleChange = (event) => {
        this.setState({quantity: event.target.value});
    };

    render() {
        const { classes, ...restProps } = this.props;
        console.log(this.state.quantity);
        return (
            <div className={classes.root}>
            <span onClick={this.decrementQty} className={classes.decrement_button}>-</span>
            <Text
                initialValue = {`${this.state.min}`}
                className={classes.quantity_input}
                field="quantity"
                onChange={this.handleChange}
                value={this.state.quantity}
                label=""
            />
            <span onClick={this.incrementQty} className={classes.increment_button}>+</span>
            </div>
    );
    }
}

export default classify(defaultClasses)(Quantity);

I have tried using value prop but its not working. If I am using uncontrolled html <input> field, the buttons and quantity increment decrement works but I don't want to use <input> element with my form.

3

2 Answers 2

1

You're right, informed Text doesn't have a prop value, I found a trick on how to set the value of the Text on a click of a button.

You can create a ref using React.createRef to your Text then set the value via this ref.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.ref = React.createRef();
  }
  state = {
    min: 10
  };
  changeQt = () => {
    this.ref.current.value = 20;
  };
  render() {
    return (
      <div className="App">
        <Text
          initialValue={`${this.state.min}`}
          field="quantity"
          onChange={this.handleChange}
          label=""
          ref={this.ref}
        />
        <button onClick={this.changeQt}>Click</button>
      </div>
    );
  }
}

Demo here.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for this demo. I am trying to implement but facing below warning Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? and an error where I am assigning value Uncaught TypeError: Cannot set property 'value' of null, Would you guide me on this.?
Can you create a sandbox for that error, so I can help you!?
I have created a demo codesandbox.io/s/mystifying-moon-3718g but here its working. Thank you for the solution, I'll check my code now and will debug the issue.
Glad to hear that it helps you. You're welcome mate
1

Maybe your code should be

 onChange={quantity => this.handleChange(quantity)}

and your code to handle state update

onChange = (e) => {
  this.setState({
    [e.target.name]: e.target.value
  });
}

3 Comments

Thank you tony for the answer but it does not update textbox value when I click on button.
onChange={quantity => this.handleChange(quantity)} does the same as onChange={this.handleChange} except that in the first case the function is recreated on every render..
I have updated question with my complete file code. As you can see I have used console.log to get quantity value and I can get correct values when I click on inc/dec buttons.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.