javascript - React 中 N 个文件输入的添加和删除

标签 javascript reactjs

我正在构建一些允许用户上传 N 个数据文件的东西。为此,我添加了一个按钮,用于创建额外的文件上传选项。这是通过渲染函数中的一个简单的 for 循环完成的(有一个选择选项仅在满足某些条件时出现,即“mergeColumnSelection”变量,您可以忽略它,但我将其包括在内,以防它以某种方式结束相关):

let renderedEnrichedDataFields = [];
for(let i = 0; i < this.state.enrichedData.length; i++) {
  let mergeColumnSelection = ""
  if(this.state.enrichedData[i] !== null) {
      mergeColumnSelection = <div className="form-item__select form-item">
        <label className="form-label" htmlFor="add-target-owner">Merging Column</label>
        <div className="form-item__container">
          <select onChange={(e) => {this.setEnrichedMergeColumn(e, i)}} defaultValue={this.state.csvColumns[0]}>
            {mainDataColumns}
          </select>
        </div>
      </div>
  }

  renderedEnrichedDataFields.push(
    <div className="form-group">
      <button onClick={() => {this.removeEnrichmentData(i)}} type="button" className="modal-close">
        <Icon name="close" />
      </button>
      <div className="form-item">
      <label className="form-label" htmlFor="add-target-csv">Enrichment Dataset</label>
        <input 
          className="csv-input" 
          type="file" 
          accept="text/csv" 
          onChange={(e) => {this.acceptNewEnrichedDataFile(e, i)}} 
        />
      </div>
      {mergeColumnSelection}

    </div>
  )
}

基本上,每次按下按钮时,都会将一个新元素推送到 state 的丰富数据数组中。这会导致应用程序呈现额外的文件输入。当用户上传文件时,数组中的占位符元素将被文件替换。当用户最终提交表单时,将提交一组文件,这很棒。

但是!我在获得一个干净的实现以删除这些输入字段的能力时遇到了很多麻烦。功能

removeEnrichmentData(index) {
  let enrichmentData = this.state.enrichedData
  let enrichedMergeColumns = this.state.enrichedMergeColumns;

  enrichmentData.splice(index, 1);
  enrichedMergeColumns.splice(index, 1)

  this.setState({enrichedData: enrichmentData, enrichedMergeColumns: enrichedMergeColumns});
}

正如您所看到的,它获取所选输入的索引,然后将其与生成 for 循环的数组进行拼接。从数组中拼接出合适的文件,文件输入的个数是正确的。但是,显示的文件名存在问题。图片会有所帮助:

Here you can see a sample where someone is preparing to upload three files, health, cluster, and starbucks

Here you can see a sample where someone is preparing to upload three files, health, cluster, and starbucks

Now I select to remove the cluster item (item 2) from the list. It is removed from the file list in state, leaving just health and starbucks. However, the for loop simply runs through twice and drops the last item - meaning that it appears that the health and cluster are the remaining two files, even though in actuality they are health and starbucks

Now I select to remove the cluster item (item 2) from the list. It is removed from the file list in state, leaving just health and starbucks. However, the for loop simply runs through twice and drops the last item - meaning that it appears that the health and cluster are the remaining two files, even though in actuality they are health and starbucks

我考虑过将 JSX block 本身移动到状态,以便我可以专门针对我想要删除的 JSX 输入元素 - 但这种方法取得的成功有限,并且了解到不建议将 JSX 置于状态。 React 并没有真正内置方法来轻松删除特定输入,而且我无法在文件输入中设置默认值,因此我无法轻松地将各个输入与其状态中的对应输入联系起来。

感觉这应该是一个如此简单的问题,但我很困惑。如有任何帮助,我们将不胜感激!

最佳答案

@Miloš Rašić 是正确的 - 您最初的问题是您可能正在使用数组索引作为输入的键。因此,如果您有 10 个编号为 0...9 的输入,并且删除了索引为 5 的输入,那么您仍然会渲染键为 0..8 的项目,并且 React 认为最后一个已被删除。

根据您关于使用 UUID 的评论,听起来您正在 render() 方法本身中生成唯一的 ID。 不要这样做! 永远不要render() 中的键生成随机值。当你这样做时,你每次都会告诉 React“这个项目与我们上次渲染的项目不同,请销毁此处现有的项目并用新的项目替换它”。

相反,当您向您的州添加新条目时,您应该生成这些唯一的 ID。例如:

class FileInputList extends Component {
    state = { inputs : [] }

    addNewFileInput = () => {
        const inputID = uuid();
        const newInputs = this.state.inputs.concat({id : inputID});
        this.setState({inputs : newInputs});
    }

    render() {
        const {inputs} = this.state;

        const inputList = inputs.map(inputEntry) => {
            return <input type="file" key={inputEntry.id} />
        });

        return inputList;
    }
}

关于javascript - React 中 N 个文件输入的添加和删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51070501/

相关文章:

javascript - 如何在 JQuery 中按字符串日期对选择下拉列表进行排序

javascript - 评估 JSON 字符串 - eval() 与 new Function()

javascript - React 循环并创建元素

javascript - 无法读取 null 的属性,mapStateToProps

javascript - WebVR 不适用于最新版本的 Firefox

javascript - 映射数组并比较至少一个巧合

reactjs - React.js 中的动态类

reactjs - 在 React 类组件中设置操作之前和之后的加载状态

javascript - 循环不适用于 react

javascript - 如何提高Vue Draggable嵌套的精度?