#javascript #reactjs
#javascript #reactjs
Вопрос:
Я создал повторитель, поэтому, когда пользователь нажимает на значок плюса, добавляется новая строка с двумя тегами ввода. Ниже приведен мой код: repeater.js
import React from "react"
const Details = (props) => {
return (
props.Desc !== '' ?
props.Desc.map((val, idx) => {
let desc = ` desc-${idx}`, file = `file-${idx}`
return (
<tr key={val.index}>
<td> Description</td>
<td >
<input type="text" defaultValue={val.desc} name="desc" data-id={idx} id={desc} className="form-control " />
</td>
<td className="mr-2"> Files</td>
<td>
<input type="file" defaultValue={file} name="file" id={file} data-id={idx} className="form-control " />
</td>
<td>
{
idx === 0 ? <button onClick={() => props.add()} type="button" className="btn btn-primary text-center"><i className="fa fa-plus-circle" aria-hidden="true"></i></button>
: <button className="btn btn-danger" onClick={(() => props.delete(val))} ><i className="fa fa-minus" aria-hidden="true"></i></button>
}
</td>
</tr >
)
})
: null
)
}
export default Details
Details.js
import React, { Fragment, Component } from 'react'
import Details from './repeater.js'
class CreateDetail extends Component {
constructor(props) {
super(props);
this.state = {
inputList: [{ index: Math.random(), desc: "", file: "" }],
}
}
onSubmit = (e) => {
console.log('data : ', this.state.inputList[0]);
}
handleChange = (e) => {
if (["desc", "file"].includes(e.target.name)) {
let Desc = [...this.state.inputList]
inputList[e.target.dataset.id][e.target.name] = e.target.value;
} else {
this.setState({ [e.target.name]: e.target.value })
}
}
addNewRow = (e) => {
this.setState((prevState) => ({
inputList: [...prevState.inputList, { index: Math.random(), desc: "", file: "" }],
}));
}
deteteRow = (index) => {
this.setState({
inputList: this.state.inputList.filter((s, sindex) => index !== sindex),
});
}
clickOnDelete(record) {
this.setState({
inputList: this.state.inputList.filter(r => r !== record)
});
}
render() {
let { inputList, flag } = this.state
return (
<Fragment>
<div className="container-fluid">
<div className="row">
<div className="col-sm-12">
<div className="card">
<div className="card-body">
<form className="needs-validation" onChange={this.handleChange}>
<div className="form-group row">
<label className="col-xl-3 col-md-3">Details</label>
<div className="col-9 col-md-9">
<table className="table">
<tbody>
<Details add={this.addNewRow} delete={this.clickOnDelete.bind(this)} Desc ={inputList} />
</tbody>
</table>
</div>
</div>
<div className="pull-right">
<button type="button" className="btn btn-primary" onClick={this.onSubmit}> save </button>
</div>
</form>
</div>
</div>
</div>
</div >
</div >
</Fragment >
)
}
}
export default CreateDetail
Но я сталкиваюсь с одной проблемой: когда я использую тип входного тега «file» и загружаю изображение, я получаю поддельный путь, как показано ниже.
C:fakepath6t8Zh249QiFmVnkQdCCtHK.jpg
Я сталкиваюсь с этой проблемой только в repeater. Если я использую входной тег с типом «file» вне repeater, то я получаю правильный путь.
Поддельный путь является основной проблемой, потому что, если я извлекаю имя файла и загружаю его в s3, тогда пустое изображение загружается в s3. Как я могу загрузить файл в repeater?
Ответ №1:
браузер не позволит получить локальный путь к файлу.вы можете использовать данные как данные формы и сохранять их в состоянии и отправлять их в S3. like
handleChange = (e) => {
let formData = new FormData
for (var i = 0; i < e.target.files.length; i ) {
formData.append(e.target.name, e.target.files[i])
}
.....
}
Комментарии:
1. Спасибо. Я использовал данные формы, и это частично решило проблему. Я имею в виду, что теперь я получаю объект file вместо поддельного пути. Но в repeater, когда я добавляю новую строку и загружаю другое изображение, я получаю только файловый объект первого изображения. Но отправка должна возвращать все загруженные изображения, что равно 2
2. теперь проверьте код. вы можете изменить имя добавляемого файла, изменив e.target.name . также e.target. файлы будут содержать выбранный вами массив файлов