通过 Ajax 在 React 中提交表单
Posted
技术标签:
【中文标题】通过 Ajax 在 React 中提交表单【英文标题】:Submitting a form in React via Ajax 【发布时间】:2019-11-21 23:39:04 【问题描述】:我的程序是这样工作的:
您从视频的选择选项菜单中选择一个视频。
选择适当的视频后(onChange 事件),将显示其字幕列表,再次选择字幕选项菜单。
选择合适的字幕后(onChange 事件),一个带有 textarea 的表单,预填充来自字幕文件的文本内容。
这东西像宣传的那样有效。当我提交(提交事件)以第三种形式更改内容时出现问题,其中包含带有字幕文本的文本区域。我需要它按两次提交按钮来提交需要写入文件的更新内容。
注意:仅在第二次提交时有效。 读取文件和其他东西是在 Laravel 中完成的,一切正常。只有这个 AJAX 部分给我带来了问题。
这是我的带有 AJAX 代码的 React 组件:
import React from 'react';
import ReactDOM from 'react-dom';
class Modsub extends React.Component
constructor(props)
super(props);
this.state =
videos: null,
subtitles: null,
subText: null,
subTextFormId: null,
;
this.select = this.select.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.getCkEditor = this.getCkEditor.bind(this);
this.getSubText = this.getSubText.bind(this);
getSubText(e)
this.setState(
subText: e.target.value,
);
getCkEditor()
console.log("got ckeditor");
CKEDITOR.replace("ckeditor");
select(e)
this.handleSubmit(e);
handleSubmit(e)
e.preventDefault();
let token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
let formId = e.target.id==="subText" ? e.target.id : e.target.parentElement.parentElement.id;
let url = "";
let formElements = ;
let myformData = new FormData();
if(formId==="videos")
url = "/modSubOfVideo";
formElements.videoId = e.target.value;
myformData.append('videoId', formElements.videoId);
if(formId==="subtitles")
url = "/openSubOfVideo";
formElements.subId = e.target.value;
this.setState(
subTextFormId: formElements.subId,
);
myformData.append('subId', formElements.subId);
if(formId==="subText")
url = "/writeSubOfVideo";
formElements.subId = e.target.elements[0].value;
formElements.subText = e.target.elements[1].value;
this.setState(
subText: formElements.subText,
);
myformData.append('subText', formElements.subText);
myformData.append('subId', formElements.subId);
myformData.append('_token', token);
myformData.append('message', "bravo");
$.ajax(
url: url,
enctype: 'multipart/form-data',
type: 'POST',
data: myformData,
dataType: 'JSON',
cache: false,
contentType: false,
processData: false,
success: (response) =>
console.log("success");
console.log(response);
if(formId==="videos")
this.setState(
subtitles: response.subtitles,
);
if(formId==="subtitles")
this.setState(
subText: response.subText,
);
//this.getCkEditor();
if(formId==="subText")
this.setState(
subText: response.subText,
);
,
error: (response) =>
console.log("error");
console.log(response);
);
componentDidMount()
//get all videos
let token = document.querySelector("meta[name='csrf-token']").getAttribute("content");
$.ajax(
url: '/addSubAjax',
type: 'POST',
data: _token: token , message: "bravo",
dataType: 'JSON',
success: (response) =>
console.log("success");
//console.log(response);
this.setState(
videos: response.videos,
);
,
error: (response) =>
console.log("error");
//console.log(response);
);
render()
/*console.log("****");
console.log(this.state);
console.log("****");*/
let videos = this.state.videos ? this.state.videos.map((item, index) =>
return <option key=index value=item.id>item.name.substr(0, 30)+"..."</option>
) : null;
let subs = this.state.subtitles ? this.state.subtitles.map((item, index) =>
return <option key=index value=item.id>item.name.substr(0, 30)+"..."</option>
) : null;
let subtitles = subs ? <form id="subtitles" encType="multipart/form-data">
<div className="form-group">
<label htmlFor="subtitles">Choose sub to modify:</label>
<select className="form-control" id="subtitlesId" name="subtitlesId" onChange=this.select required>
subs
</select>
</div>
</form>
: "";
let subTextPre = "<pre>"+this.state.subText+"</pre>";
let subText = this.state.subText ? <form id="subText" onSubmit=this.handleSubmit encType="multipart/form-data">
<div className="form-group">
<input type="hidden" name="subId" value=this.state.subTextFormId/>
<label htmlFor="subText">Modify subtitle:</label>
<textarea className="form-control" id="ckeditor" rows="5" onChange=this.getSubText name="subTextId" defaultValue=subTextPre/>
</div>
<button type="submit" className="btn btn-outline-primary">Submit</button>
</form>
: "";
return (
<div className="container">
<form id="videos" encType="multipart/form-data">
<div className="form-group">
<label htmlFor="video">Choose video:</label>
<select className="form-control" id="videoId" name="videoId" onChange=this.select required>
videos
</select>
</div>
</form>
subtitles
subText
</div>
);
if(document.getElementById('modsub'))
ReactDOM.render(<Modsub/>, document.getElementById('modsub'));
考虑到我以前的问题,我可能没有看到明显的......尽管如此,如果你们中的任何一个善良的灵魂能指出我正确的方向,我将不胜感激。提前多点赞:D
EDIT1:
我有点弄清楚是什么导致了问题。这是ckeditor的调用。通过从handleSubmit()
方法中的条件中删除this.getCkEditor();
,一切正常。但是如何使它与 ckeditor 一起工作?
【问题讨论】:
您能否简化您的问题和代码并提供一个最低限度的示例或代码笔? @christianeide Bare minimum willhandleSubmit
方法,因为我确定其中存在问题。问题简化:为什么我的表单需要提交,使用 handleSubmit onSubmit 事件,两次才能使更改生效?
能把这个问题不需要的所有不必要的函数和方法去掉吗?这仍然是需要审查和进入的大量代码。遵循这些准则***.com/help/minimal-reproducible-example
@christianeide 已编辑。看看编辑说明。
是表单肯定没有提交,还是您第一次收到 ajax 错误响应?
【参考方案1】:
听起来像是一个异步问题。尝试向 ckeditor 添加回调,以确保在 ckeditor 完成后进行 Axiom 调用。
【讨论】:
【参考方案2】:我终于明白了。如何做到这一点,而不是为什么会发生。 所以,这里是:
就在 handleSubmit
方法中的 ajax 调用之前,我添加了
if(CKEDITOR.instances['ckeditor'])
formElements.subText = CKEDITOR.instances['ckeditor'].getData();
myformData.append('subText', formElements.subText);
从 ckeditor 实例中手动“翻录”文本内容并使用它设置myformData
。我不知道为什么或如何,但它有效。通过阅读众多论坛上的大量帖子和答案,我得出的结论是,这只是 ckeditor 的一些怪癖。特别是如果您将它与 ajax 一起使用,更不用说使用更多框架,前端和后端都一样。
感谢大家的指导。
【讨论】:
以上是关于通过 Ajax 在 React 中提交表单的主要内容,如果未能解决你的问题,请参考以下文章