Маска ввода не работает при удалении значения

Я создал функцию для маскировки ввода при наборе текста, и она отлично работает, но при удалении значения на вводе маска ведет себя странно.

function App() {
const [phone, setPhone] = React.useState('')

  function maskPhone({ target: { value } }) {
		console.log(value)
		const toMatch = value.replace(/\D/g, '')
    const regex = /(\d{0,2})(\d{0,1})(\d{0,4})(\d{0,4})/
		const [,ddd, prefix, first, second] = toMatch.match(regex)
		setPhone(`(${ddd}) ${prefix} ${first} ${second}`)
	}
  
  return  <div>
      phone: <input type='text' onChange={maskPhone} value={phone} />
  </div>
}

ReactDOM.render(<App/>, document.querySelector('#root'))
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>


person Jefter Rocha    schedule 26.03.2020    source источник


Ответы (1)


Вам нужно сделать почти все части регулярного выражения необязательными с шаблоном типа (?:\s*(\d{n,m}))?, а затем проверить, соответствует ли группа, и динамически построить шаблон замены. Первая часть со скобками также нуждается в настройке из-за этих скобок.

Вот рабочее решение:

function App() {
const [phone, setPhone] = React.useState('')

function maskPhone({ target: { value } }) {
    console.log(value)
    var reg  = /^(\d{1,2})(?:\s*(\d)(?:\s*(\d{1,4})(?:\s*(\d{1,4}))?)?)?$/
    setPhone(value.replace(/\D/g,'').replace(reg, (_,w,x,y,z) =>  
       ( w.length>0 ? `(${w}` : "") + ( x ? `) ${x}` : "") + ( y ? ` ${y}` : "") + ( z ? ` ${z}` : "") ))
    }
  
  return  <div>
      phone: <input type='text' onChange={maskPhone} value={phone} />
  </div>
}

ReactDOM.render(<App/>, document.querySelector('#root'))
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

person Wiktor Stribiżew    schedule 26.03.2020