【问题标题】:Javascript splice array method is not working as expectedJavascript 拼接数组方法未按预期工作
【发布时间】:2023-02-08 01:43:29
【问题描述】:

,

我正在研究 js 的 splice 方法,但看起来它并没有完全按照它应该从数组中删除任何元素的方式工作。

目前它只删除数组中的最后一个元素,即使在为它提供索引值以从数组中删除之后也是如此。在 console.log 中,我在删除任何内容后得到了完美的输出,但在 UI 部分它没有更新,即使我单击删除其他项目,它也只是从数组中删除最后一个元素。我该如何解决这个问题?

到目前为止,这是我尝试过的:

 const add_actions_options = [
    {value : "Postback" , label:intl.formatMessage({ id: 'POSTBACK' })},
    {value : "Uri" , label:intl.formatMessage({ id: 'URI' })}
  ]

  const [ actions , setActions ] = useState<any | undefined>([{type : add_actions_options[0].value , label : "" , data : ""}])
  const [selectOptions, setSelectOptions] = useState<any>(add_actions_options);


  function addAction(){
    if(actions.length < 4 ){
      setSelectOptions([...add_actions_options])
      setActions([...actions , {type : selectOptions[0].value , label : "" , data : ""}])
   } else {
    toast(intl.formatMessage({ id: 'MAX.ALLOWED.4' }), { type: "error" })  
    }
  }

  function deleteAction(index){
    if(actions.length === 1 ){
      toast(intl.formatMessage({ id: 'MIN.ALLOWED.1' }), { type: "error" })  
   } else {
    const updatedFields = [...actions];
    updatedFields.splice(index, 1);
    console.log('index : ' , index)
    console.log('updatedFields : ' , updatedFields)
    setActions(updatedFields);
    }
  }

 <div className='row my-6'>
                  <div className='col-lg-3 py-2'>
                  <h4><label className="form-label">{intl.formatMessage({ id: 'ACTIONS' })}*</label></h4>
                   <button className='btn btn-primary btn-sm btn-block' onClick={() => addAction()}>
                   <KTSVG path='/media/icons/duotune/arrows/arr075.svg' className='svg-icon-2' />
                    {intl.formatMessage({id: 'ADD.ACTION'})}
                   </button>
                  </div>
                </div>
                <div className='row my-6 '>
                      { actions.map((item , index) => {
                          return(
                            <div key={index} className='row my-6'>
                               <div className='col-lg-4 py-2'>
                                 <h4><label className="form-label">{intl.formatMessage({ id: 'TEMPLATE.TYPE' })}*</label></h4>
                                 <Select
                                    onChange={(value) => handleTypeChange(index, value)}
                                    options={selectOptions}
                                  />
                               </div>
                               <div className='col-lg-3 py-2'>
                                 <h4><label className="form-label">{intl.formatMessage({ id: 'TEMPLATE.LABEL' })}*</label></h4>
                                 <input
                                      {...formik_buttons_type.getFieldProps('action.label')}
                                      className="form-control form-control-lg form-control-solid"
                                      name='action.label'
                                      id='action_label'
                                      type="text"
                                      maxLength={30}
                                      onChange={(event) => handleLabelChange(index, event.target.value)}
                                      value={actions.label}
                                      required
                                      onInvalid={(e) => checkLabelValidation(e)} 
                                      onInput={(e) => checkLabelValidation(e)}
                                     />
                               </div>
                               <div className='col-lg-3 py-2'>
                                 <h4><label className="form-label">{intl.formatMessage({ id: 'TEMPLATE.DATA' })}*</label></h4>
                                 <input
                                      {...formik_buttons_type.getFieldProps('action.data')}
                                      className="form-control form-control-lg form-control-solid"
                                      name='action.data'
                                      id='action_data'
                                      type="text"
                                      maxLength={100}
                                      onChange={(event) => { handleDataChange(index, event.target.value); }}
                                      value={actions.data}
                                      required
                                      onInvalid={(e) => checkDataValidation(e)} 
                                      onInput={(e) => checkDataValidation(e)}
                                     />

                               </div>
                               <div className='col-lg-2 py-2 mt-10'>
                               <OverlayTrigger
                                   delay={{ hide: 50, show: 50 }}
                                   overlay={(props) => (
                                     <Tooltip {...props}>
                                       {intl.formatMessage({ id: 'DEL.ACTION' })}
                                     </Tooltip>
                                   )}
                                   placement="top">
                                  <button
                                     type='button'
                                     style={{display: index === 0 ? 'none': 'inline-block'}} 
                                     className='btn btn-icon btn-md btn-bg-light btn-color-danger me-1'
                                     onClick={() => deleteAction(index)}
                                    >
                                     <i className='fa fa-trash'></i>
                                 </button>                               
                                </OverlayTrigger>
                               </div>
                              
                            </div>
                          )
                        })}
                </div>

我能够从下面的 deleteAction 字段中的日志中接收到准确的索引号完美输出,但是浏览器中的视图从操作数组中删除了最后一列(索引)。 :

 console.log('index : ' , index)
 console.log('updatedFields : ' , updatedFields)

谁能帮我这个 ?

感谢致敬 !

【问题讨论】:

    标签: javascript reactjs arrays typescript react-functional-component


    【解决方案1】:

    https://reactjs.org/docs/lists-and-keys.html

    如果项目的顺序可能会改变,我们不建议对键使用索引。这会对性能产生负面影响,并可能导致组件状态出现问题。

    当你做

    { actions.map((item , index) => {
        return(
            <div key={index}
    

    您几乎是在询问组件状态的问题。当 React 试图确定要更新 UI 中的哪个元素时,它会看到“长度为 6 的数组现在长度为 5,我需要删除哪个元素”,它会找到一个带有键的元素不再存在,在这种情况下是最后一个,因为您使用索引作为键,并将删除它。

    我可能会做

    function randomId(){
        const uint32 = window.crypto.getRandomValues(new Uint32Array(1))[0];
        return uint32.toString(16);
    }
    
    const [ actions , setActions ] = useState<any | undefined>([{id: randomId(), type : add_actions_options[0].value , label : "" , data : ""}])
    
    function addAction(){
        if(actions.length < 4 ){
            setSelectOptions([...add_actions_options])
            setActions([...actions , {id: randomId(), type : selectOptions[0].value , label : "" , data : ""}])
        } else {
            toast(intl.formatMessage({ id: 'MAX.ALLOWED.4' }), { type: "error" })  
        }
    }
    
    { actions.map((item) => {
        return(
            <div key={item.id}
    

    其中 randomId 可以是任何可以为您提供唯一 ID 的内容,或者(甚至更好)如果实际数据上存在唯一标识它的现有属性,您可以使用它。

    【讨论】:

    • 嗨@dave 感谢你的努力,这没有成功,但它也会抛出错误:“警告:列表中的每个孩子都应该有一个唯一的“关键”道具。”
    猜你喜欢
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-11
    • 2019-04-22
    相关资源
    最近更新 更多