React: Regex not working

React: Regex not working
0

#1

I keep getting “unnecesary escape character” when I use it:

this.setState(prevState => ({ value:  `${prevState.value}${result}` .replace( `${/^\d*([/\+-/*=]\d+)*$/gi}` ) }));

#2

Not seeing anything wrong with this one line. I would need to see your full code to test out a few things.


#3

Thanks for the reply. My idea is for this Regex to limit both operators (only one everytime) and the decimals.
Calculator

class Calculator extends Component {
  constructor(props) {
    super(props);
    this.state = {value:""}
  this.handleClick = this.handleClick.bind(this);
      }
  handleClick(evt){
 const id=evt.target.id;
 const result= evt.target.value;

this.setState(prevState =({ value:  `${prevState.value}${result}` .replace( `${/^\d*([/\+-/*=]\d+)*$/gi}` ) }));


if(id==="equals"){
    this.setState({value: math.eval(this.state.value)})
}
else if(id==="clear"){
this.setState({value : 0})  
 }

}



render() {
    return(
            <div id="container">
                <Display value={this.state.value} />
                <Button onClick={this.handleClick} id="zero" value={'0'} />
                <Button onClick={this.handleClick} id="one" value={'1'} />
                <Button onClick={this.handleClick} id="two" value={'2'}/>
                <Button onClick={this.handleClick} id="three" value={'3'} />
                <Button onClick={this.handleClick} id="four" value={'4'} />
                <Button onClick={this.handleClick} id="five" value={'5'} />
                <Button onClick={this.handleClick} id="six" value={'6'} />
                <Button onClick={this.handleClick} id="seven" value={'7'} />
                <Button onClick={this.handleClick} id="eight" value={'8'}  />
                <Button onClick={this.handleClick} id="nine" value={'9'} />
                <Button onClick={this.handleClick} id="decimal" value={'.'} />
                <Button onClick={this.handleClick} id="equals" value={'='} />
                <Button onClick={this.handleClick} id="clear" value={'clear'}  />
                <Button onClick={this.handleClick} id="add" value={'+'} />
                <Button onClick={this.handleClick} id="subtract" value={'-'} />
                <Button onClick={this.handleClick} id="multiply" value={'*'} />
                <Button onClick={this.handleClick} id="divide" value={'/'} />
            </div>
)

}
}

#4

Mind posting your Button and Display components? I don’t want to recreate them.


#5

Yes, of course!

Button

const Button = (props) => {
  return (
    <input type="button" onClick={props.onClick} id={props.id} value={props.value} />

)

};

Display

const Display = (props) => {
  return (
    		<div>

    			<h2 id="display">{props.value} </h2>

    		</div>
)};

#6

Sorry, just realised one line was wrong in the calculator:

this.setState(prevState => ({
  value: `${prevState.value}${result}`.replace( `${/^\d*([/\+-/*=]\d+)*$/gi}` )
}));

#7

I am not getting an error like you describe. How do I replicate your issue? What sequence of actions must I do to see the error?

I am getting math is not defined on from this line:

      this.setState({ value: math.eval(this.state.value) });

If I delete math., then the calculator seems to work fine.

Entering the following
image
and clicking = yields
image


#8

This is SO bizarre. I created the app using Create React App. Math is Math.js, which is imported with: import * as math from mathjs after installing it.
I run the app with npm start, and I get:
./src/App.js
Line 17: Unnecessary escape character: + no-useless-escape

which prevents the Regex from enforcing any format. I´ll paste the line again, but I am quite sure I am using the template literals correctly:

this.setState(prevState => ({
  value: `${prevState.value}${result}`.replace( `${/^\d*([/\+-/*=]\d+)*$/gi}` )
}));

You do not need the template literal for the replace, regular expression, but you also do need to escape the ., - , and *. You will still need to figure out what you want to replace a match to this expression with and put it as the 2nd argument.

this.setState(prevState => ({
  value: `${prevState.value}${result}`.replace(/^\d*([\/\+-/*=]\d+)*$/gi, replacementValue)
}));

Just remember what ever this regular expression matches, will be replaced by what ever you specify for replacementValue.

I think something like the following may work:

    this.setState(prevState => ({
      value: `${prevState.value}${result}`.replace(/([\/\+-/*=])([\/\+\-\*=])/gi, '$2')
    }));

This probably could be a shorter regex, but for now it should work. Basically you have two capture groups for the same same character set. If you get two consecutive characters from the these characters sets, then the character gets replaced by the character in the 2nd capture group.


#9

i recommend posting a link to your project (i.e. Codepen), because there must be some other code than what you posted causing the problem.


#10

But is it enforcing the format? (not allowing concatenation of operators, or decimals, etc)


#11

Can you provide an example of what I should test?


#12

For instance, 5++++5 shouldn´t be allowed, it should only be 5+5. And if you input 5±5 it should automatically become 5-5.


#13

Your replace is missing a second argument (the replacement value). Also, you are using a string instead of an actual regular expression.


#14

Really? But my previous Regex (I used one before to stop the user from submitting 00) worked fine with this syntax. This is weird. How can I fix it? Thanks a lot for all the effort btw!


#15

By fix it, I mean: make it work the way I intended. I should probably do an if statement to check if the input matches the regex format, AND THEN update state (or return undefined) afterwards, right?


#16

My suggestion is as follows:

this.setState(prevState => ({
  value: `${prevState.value}${result}`.replace(/([\/\+-/*=])([\/\+\-\*=])/gi, '$2')
}));

There are two identical capture groups containing the same character set. If two consecutive characters are found in this character set, then the match gets replaced by the character in the 2nd capture group.


#17

Thank you, this works. Now I just need to add two conditions to the Regex: no leading zeros and no more than one decimal.


#18

I know you will figure it out.


#19

Ok, so i got a bunch of Regex. But I don´t know in which order to apply them. For instance:
For instance, removing leading zeros:

 /^0+(?=[1-9])/ (I replace with a zero)

I thought about applying this to the zero button before setting state, but it isn´t working.
Same with this one in the decimal number:

/\.+/g (I replace with one dot)

Any ideas on how to do this? It´s really beggining to be frustrating.