简体   繁体   中英

React onChange rerender dynamic input fields strange

When changing data in dynamic fields, my functional component copies the current field and redraws the field and adds it to the end of the form. I displayed input fields via Object.keys.map and put there state and check type with switch, after display text, number, checkbox fields together.

import React, { useState } from 'react'

const Form = () => {

  const [state, setState] = useState({
    companyName: "seenus",
    tradeName: "ТОРТАЙ О.А ИП",
    description: "",
    email: "olzhastortay@gmail.com",
    region: "Almaty",
    phone: "(707) 795-15-09",
    bin: "",
    code: "",
    isActive: true,
    merchant_terminal: {
      terminal_id: "98264471",
      saveCard: false,
      isActive: true,
      currencyName: "KZT",
      isAmexAllowed: false,
      sendBack: false,
      parentId: "",
      B64ENCODE: false,
      persLimit: 0,
      isRecurAllowed: false,
      shouldUseNewKey: true,
      minSum: 0,
      postlinkTries: 0,
      MCC: 0,
      dailyLimit: 0,
      isFromEpay1: false,
      permitted_countries: "",
      forbidden_countries: ""
    }
  })

  
  const iterate = (obj: any): any => {
    
    return Object.keys(obj).map((key) => {

      switch(typeof obj[key]) {
        case 'object': 
          return iterate(obj[key])

        case 'string': 

          return (
            <div className="section-form" key={key}>
                <TextField 
                  label={key} 
                  variant="outlined"
                  defaultValue={obj[key]}
                  onChange={handleChange(key)}
                />
            </div>
          )

        case 'number': 
        
          return (
            <div className="section-form" key={key}>
                <TextField 
                  label={key} 
                  variant="outlined" 
                  type="number"
                  defaultValue={obj[key]}
                  onChange={handleChange(key)}
                />
            </div>
          )

        case 'boolean': 
        
          console.log('boolean inside')
          return (
            <div className="section-form" key={key}>
              <FormControlLabel
                control={<Switch checked={obj[key]} onChange={handleChange(key)} />}
                label={key}
              />
            </div>
          )

      }

    })

  }


  const handleChange = (prop: any) => (event: any) => {
    
    const {checked, value, type} = event.target
    
    switch (type) {
      case 'checkbox':
        return setState((prev: any) => ({...prev, [prop]: checked}))
      default: 
        return setState((prev: any) => ({...prev, [prop]: value}))
    }

  }

  return (
    <form>
      <h1 className="merch-title">Страница нового коммерсанта</h1>
      <div className="merch-form">
        { iterate(state) }
      </div>
      <div className="merch-btn">
        <Button size="large" variant="contained" type="submit" color="primary">
            создать коммерсанта
        </Button>
      </div>
      
    </form>
  )

}

export default Form

input fields IMAGE

const handleChange = (arr?: any) => (event: any) => {
    
        const {checked, value, type} = event.target
    
        let tmp = state
        const depth = arr.length -1
        
        for (let i = 0; i < arr.length; i++) {
          const depthKey = arr[i]
          
          if(i < depth) {
            tmp = tmp[depthKey]
          }
          if(i === depth) {
            tmp[depthKey] = (type === 'checkbox') ? checked : value
          }
    
        }
    
        return setState({...state})
    
      }

The problem was in state. Every time when I returned state with nested object, I was returing first depth of object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM