我试图为一个音频文件实现一个on-change处理程序,当用户更改文件时,该处理程序会加载文件的先前状态并记录下来。
更具体地说。当用户进入组件时,文件的链接应该显示在窗体字段中,当用户更新文件时,文件的新路径应该被on-change处理程序记录下来。
目前,on-change处理程序对音频文件是有效的。 然而,之前的文件没有被加载,所以当组件加载时,文件的表单字段仍然是空的。我没有收到错误信息,因此目前很难解决这个问题。
从后台成功获取了文件(我可以加载之前的标题状态,而内容只是对于文件字段其不工作)。
export class EditStory extends Component {
constructor(props) {
super(props);
this.getStory = this.getStory.bind(this);
this.updateStory = this.updateStory.bind(this);
this.onChangeTitle = this.onChangeTitle.bind(this);
this.onChangeContent=this.onChangeContent.bind(this);
this.onChangeAudio=this.onChangeAudio.bind(this);
this.inputRef = React.createRef();
this.state = {
story: {
id: null,
title: "",
content: "",
audio: ""
}
};
}
componentDidMount() {
this.getStory(this.props.match.params.id);
}
onChangeTitle(e) {
const title = e.target.value;
this.setState(prevState => ({
story: {
...prevState.title,
title: title
}
}), () => console.log(this.state));
}
onChangeContent(e) {
const content = e.target.value;
this.setState(prevState => ({
story: {
...prevState.story,
content: content
}
}), () => console.log(this.state));
}
onChangeAudio(e) {
const audio = e.target.name;
this.setState(prevState => ({
story: {
...prevState.story,
[e.target.name]: e.target.files[0]
}
}), () => console.log(this.state.audio));
}
getStory(id) {
this.props.getSingleStory(id)
.then(response => {
this.setState({
story: response.data
});
console.log(response.data);
;
})
.catch(e => {
console.log(e);
});
}
updateStory() {
const id = this.state.story.id;
let title = this.state.story.title;
let content = this.state.story.content;
let audio = this.state.story.audio;
let UpdatedData = new FormData();
UpdatedData.append('audio', audio); // add audio to formData
UpdatedData.append('title', title); // add title to formData
UpdatedData.append('content', content);
console.log (UpdatedData);
this.props.editStory(
id,
UpdatedData
)
.then(response => {
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
static propTypes = {
getSingleStory: PropTypes.func.isRequired,
editStory: PropTypes.func.isRequired
};
render() {
const {story} = this.state;
return (
<div>
<h1>Edit {story.title}</h1>
<div className="form-group">
<label>Title</label>
<input type="text" name="title" defaultValue={story.title} onChange={this.onChangeTitle} className="form-control" />
</div>
<div className="form-group">
<label>Content</label>
<textarea name="content" rows="5" defaultValue={story.content} onChange={this.onChangeContent} className="form-control" />
</div>
<div className="form-group">
<label>Audio</label>
<input
className="form-control"
type="file"
name="audio"
onChange={this.onChangeAudio}
ref={this.inputRef} // refer to ref
/>
</div>
<div className="btn-group">
<button type="submit" onClick={this.updateStory} className="btn btn-dark">Update</button>
<button type="button" className="btn btn-secondary">Cancel</button>
</div>
</div>
);
}
}
export default connect(
null,
{ getSingleStory, editStory, }
)(EditStory);
可能是什么原因呢?
当你从服务器获取数据时,你可以通过在inputRef上设置文件键来动态设置输入字段的值。 然而,你需要将传入的文件转换为以下格式 FileList
使用 DataTransfer
构造函数。你可以在这篇文章中找到更多信息。如何在FileList对象上设置文件对象和长度属性,使文件也反映在FormData对象上?
你更新了代码。
getStory(id) {
this.props.getSingleStory(id)
.then(response => {
this.setState({
story: response.data
});
const file = new File(response.data.file, "filename.txt, {
type: "text/plain",
});
const dT = new ClipboardEvent('').clipboardData || new DataTransfer();
dT.items.addfile(file);
this.inputRef.current.files = dT.files;
;
})
.catch(e => {
console.log(e);
});
}