Javascript 如何在不刷新页面的情况下立即在React中显示提交的数据?
我正在开发一个简单的笔记应用程序,我正在尝试在笔记列表的末尾添加新的笔记,然后立即看到添加的笔记。不幸的是,我只能通过刷新页面来完成。有没有更简单的方法 我知道改变状态通常会有所帮助,但我有两个独立的组件,我不知道如何以任何方式连接它们 因此,在NewNoteForm组件中,我有一个提交操作:Javascript 如何在不刷新页面的情况下立即在React中显示提交的数据?,javascript,reactjs,Javascript,Reactjs,我正在开发一个简单的笔记应用程序,我正在尝试在笔记列表的末尾添加新的笔记,然后立即看到添加的笔记。不幸的是,我只能通过刷新页面来完成。有没有更简单的方法 我知道改变状态通常会有所帮助,但我有两个独立的组件,我不知道如何以任何方式连接它们 因此,在NewNoteForm组件中,我有一个提交操作: doSubmit = async () => { await saveNote(this.state.data); }; 然后在主组件中,我只传递NewNoteForm组件 下面是
doSubmit = async () => {
await saveNote(this.state.data);
};
然后在主组件中,我只传递NewNoteForm组件
下面是整个NewNoteForm组件:
import React from "react";
import Joi from "joi-browser";
import Form from "./common/form";
import { getNote, saveNote } from "../services/noteService";
import { getFolders } from "../services/folderService";
class NewNoteForm extends Form {
//extends Form to get validation and handling
state = {
data: {
title: "default title",
content: "jasjdhajhdjshdjahjahdjh",
folderId: "5d6131ad65ee332060bfd9ea"
},
folders: [],
errors: {}
};
schema = {
_id: Joi.string(),
title: Joi.string().label("Title"),
content: Joi.string()
.required()
.label("Note"),
folderId: Joi.string()
.required()
.label("Folder")
};
async populateFolders() {
const { data: folders } = await getFolders();
this.setState({ folders });
}
async populateNote() {
try {
const noteId = this.props.match.params.id;
if (noteId === "new") return;
const { data: note } = await getNote(noteId);
this.setState({ data: this.mapToViewModel(note) });
} catch (ex) {
if (ex.response && ex.response.status === 404)
this.props.history.replace("/not-found");
}
}
async componentDidMount() {
await this.populateFolders();
await this.populateNote();
}
mapToViewModel(note) {
return {
_id: note._id,
title: note.title,
content: note.content,
folderId: note.folder._id
};
}
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
doSubmit = async () => {
await saveNote(this.state.data);
};
render() {
return (
<div>
<h1>Add new note</h1>
<form onSubmit={this.handleSubmit}>
{this.renderSelect("folderId", "Folder", this.state.folders)}
{this.renderInput("title", "Title")}
{this.renderInput("content", "Content")}
{this.renderButton("Add")}
</form>
</div>
);
}
}
export default NewNoteForm;
import React, { Component } from "react";
import { getNotes, deleteNote } from "../services/noteService";
import ListGroup from "./common/listGroup";
import { getFolders } from "../services/folderService";
import { toast } from "react-toastify";
import SingleNote from "./singleNote";
import NewNoteForm from "./newNoteForm";
class Notes extends Component {
state = {
notes: [], //I initialize them here so they are not undefined while componentDidMount is rendering them, otherwise I'd get a runtime error
folders: [],
selectedFolder: null
};
async componentDidMount() {
const { data } = await getFolders();
const folders = [{ _id: "", name: "All notes" }, ...data];
const { data: notes } = await getNotes();
this.setState({ notes, folders });
}
handleDelete = async note => {
const originalNotes = this.state.notes;
const notes = originalNotes.filter(n => n._id !== note._id);
this.setState({ notes });
try {
await deleteNote(note._id);
} catch (ex) {
if (ex.response && ex.response.status === 404)
toast.error("This note has already been deleted.");
this.setState({ notes: originalNotes });
}
};
handleFolderSelect = folder => {
this.setState({ selectedFolder: folder }); //here I say that this is a selected folder
};
render() {
const { selectedFolder, notes } = this.state;
const filteredNotes =
selectedFolder && selectedFolder._id //if the selected folder is truthy I get all the notes with this folder id, otherwise I get all the notes
? notes.filter(n => n.folder._id === selectedFolder._id)
: notes;
return (
<div className="row m-0">
<div className="col-3">
<ListGroup
items={this.state.folders}
selectedItem={this.state.selectedFolder} //here I say that this is a selected folder
onItemSelect={this.handleFolderSelect}
/>
</div>
<div className="col">
<SingleNote
filteredNotes={filteredNotes}
onDelete={this.handleDelete}
/>
<NewNoteForm />
</div>
</div>
);
}
}
export default Notes;
doSubmit/handleSubmit = async (event) => {
event.preventDefault();
event.stopPropagation();
const newNote = await saveNote(this.state.data);
this.props.onNewNoteCreated(newNote);
}
从“React”导入React;
从“Joi浏览器”导入Joi;
从“/common/Form”导入表单;
从“./services/noteService”导入{getNote,saveNote};
从“./services/folderService”导入{getFolders};
类NewNoteForm扩展了表单{
//扩展表单以获得验证和处理
状态={
数据:{
标题:“默认标题”,
内容:“Jasjdhajhdjshjahjahdjh”,
folderId:“5d6131ad65ee332060bfd9ea”
},
文件夹:[],
错误:{}
};
模式={
_id:Joi.string(),
标题:Joi.string().label(“标题”),
内容:Joi.string()
.required()
.标签(“注”),
folderId:Joi.string()
.required()
.标签(“文件夹”)
};
异步populateFolders(){
const{data:folders}=wait getFolders();
this.setState({folders});
}
异步populateNote(){
试一试{
const noteId=this.props.match.params.id;
如果(noteId==“new”)返回;
const{data:note}=wait-getNote(noteId);
this.setState({data:this.mapToViewModel(note)});
}捕获(ex){
if(ex.response&&ex.response.status==404)
this.props.history.replace(“/未找到”);
}
}
异步组件didmount(){
等待这个消息。populateFolders();
等待这个消息;
}
mapToViewModel(注){
返回{
_id:注意.\u id,
标题:note.title,
内容:note.content,
folderId:note.folder.\u id
};
}
scrollToBottom=()=>{
this.messagesEnd.scrollIntoView({behavior:“smooth”});
}
doSubmit=async()=>{
等待saveNote(this.state.data);
};
render(){
返回(
添加新注释
{this.renderSelect(“folderId”,“Folder”,this.state.folders)}
{this.renderInput(“title”,“title”)}
{this.renderInput(“content”,“content”)}
{this.renderButton(“Add”)}
);
}
}
导出默认的NewNoteForm;
这是整个主要部分:
import React from "react";
import Joi from "joi-browser";
import Form from "./common/form";
import { getNote, saveNote } from "../services/noteService";
import { getFolders } from "../services/folderService";
class NewNoteForm extends Form {
//extends Form to get validation and handling
state = {
data: {
title: "default title",
content: "jasjdhajhdjshdjahjahdjh",
folderId: "5d6131ad65ee332060bfd9ea"
},
folders: [],
errors: {}
};
schema = {
_id: Joi.string(),
title: Joi.string().label("Title"),
content: Joi.string()
.required()
.label("Note"),
folderId: Joi.string()
.required()
.label("Folder")
};
async populateFolders() {
const { data: folders } = await getFolders();
this.setState({ folders });
}
async populateNote() {
try {
const noteId = this.props.match.params.id;
if (noteId === "new") return;
const { data: note } = await getNote(noteId);
this.setState({ data: this.mapToViewModel(note) });
} catch (ex) {
if (ex.response && ex.response.status === 404)
this.props.history.replace("/not-found");
}
}
async componentDidMount() {
await this.populateFolders();
await this.populateNote();
}
mapToViewModel(note) {
return {
_id: note._id,
title: note.title,
content: note.content,
folderId: note.folder._id
};
}
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
doSubmit = async () => {
await saveNote(this.state.data);
};
render() {
return (
<div>
<h1>Add new note</h1>
<form onSubmit={this.handleSubmit}>
{this.renderSelect("folderId", "Folder", this.state.folders)}
{this.renderInput("title", "Title")}
{this.renderInput("content", "Content")}
{this.renderButton("Add")}
</form>
</div>
);
}
}
export default NewNoteForm;
import React, { Component } from "react";
import { getNotes, deleteNote } from "../services/noteService";
import ListGroup from "./common/listGroup";
import { getFolders } from "../services/folderService";
import { toast } from "react-toastify";
import SingleNote from "./singleNote";
import NewNoteForm from "./newNoteForm";
class Notes extends Component {
state = {
notes: [], //I initialize them here so they are not undefined while componentDidMount is rendering them, otherwise I'd get a runtime error
folders: [],
selectedFolder: null
};
async componentDidMount() {
const { data } = await getFolders();
const folders = [{ _id: "", name: "All notes" }, ...data];
const { data: notes } = await getNotes();
this.setState({ notes, folders });
}
handleDelete = async note => {
const originalNotes = this.state.notes;
const notes = originalNotes.filter(n => n._id !== note._id);
this.setState({ notes });
try {
await deleteNote(note._id);
} catch (ex) {
if (ex.response && ex.response.status === 404)
toast.error("This note has already been deleted.");
this.setState({ notes: originalNotes });
}
};
handleFolderSelect = folder => {
this.setState({ selectedFolder: folder }); //here I say that this is a selected folder
};
render() {
const { selectedFolder, notes } = this.state;
const filteredNotes =
selectedFolder && selectedFolder._id //if the selected folder is truthy I get all the notes with this folder id, otherwise I get all the notes
? notes.filter(n => n.folder._id === selectedFolder._id)
: notes;
return (
<div className="row m-0">
<div className="col-3">
<ListGroup
items={this.state.folders}
selectedItem={this.state.selectedFolder} //here I say that this is a selected folder
onItemSelect={this.handleFolderSelect}
/>
</div>
<div className="col">
<SingleNote
filteredNotes={filteredNotes}
onDelete={this.handleDelete}
/>
<NewNoteForm />
</div>
</div>
);
}
}
export default Notes;
doSubmit/handleSubmit = async (event) => {
event.preventDefault();
event.stopPropagation();
const newNote = await saveNote(this.state.data);
this.props.onNewNoteCreated(newNote);
}
import React,{Component}来自“React”;
从“./services/noteService”导入{getNotes,deleteNote};
从“/common/ListGroup”导入列表组;
从“./services/folderService”导入{getFolders};
从“react toastify”导入{toast};
从“/SingleNote”导入SingleNote;
从“/NewNoteForm”导入NewNoteForm;
类注释扩展了组件{
状态={
注意:[],//我在这里初始化它们,以便在componentDidMount呈现它们时它们不会未定义,否则会出现运行时错误
文件夹:[],
selectedFolder:空
};
异步组件didmount(){
const{data}=wait getFolders();
const folders=[{u id:,name:“All notes”},…data];
const{data:notes}=wait getNotes();
this.setState({notes,folders});
}
handleDelete=异步注释=>{
const originalNotes=this.state.notes;
const notes=originalNotes.filter(n=>n.\u id!==note.\u id);
this.setState({notes});
试一试{
等待删除注释(注释编号);
}捕获(ex){
if(ex.response&&ex.response.status==404)
toast.error(“此注释已被删除”);
this.setState({notes:originalNotes});
}
};
handleFolderSelect=文件夹=>{
this.setState({selectedFolder:folder});//这里我说这是一个选中的文件夹
};
render(){
const{selectedFolder,notes}=this.state;
康斯特过滤器酒店=
selectedFolder&&selectedFolder.\u id//如果所选文件夹为truthy,我将获取具有此文件夹id的所有便笺,否则我将获取所有便笺
?notes.filter(n=>n.folder.\u id===selectedFolder.\u id)
:附注;
返回(
);
}
}
导出默认票据;
如何连接这两个组件,以便在提交后数据能够顺利显示?您可以使用类似回调的模式在子组件和其父组件之间进行通信(这是@FrankerZ链接中的第三种策略) src:) 实际上,您将函数传递到子组件中(在main/parent component=“Notes”中):
其中,onNewNoteCreated
可以接受类似新注释的内容(原始数据或来自服务的响应)作为参数,并将其保存到父级的本地状态,然后由任何感兴趣的子组件(即列表组
)使用
示例onNewNoteCreated
实现:
onNewNoteCreated = (newNote) => {
this.setState({
notes: [...this.state.notes, newNote],
});
}
在NewNoteForm
组件中使用的示例:
import React from "react";
import Joi from "joi-browser";
import Form from "./common/form";
import { getNote, saveNote } from "../services/noteService";
import { getFolders } from "../services/folderService";
class NewNoteForm extends Form {
//extends Form to get validation and handling
state = {
data: {
title: "default title",
content: "jasjdhajhdjshdjahjahdjh",
folderId: "5d6131ad65ee332060bfd9ea"
},
folders: [],
errors: {}
};
schema = {
_id: Joi.string(),
title: Joi.string().label("Title"),
content: Joi.string()
.required()
.label("Note"),
folderId: Joi.string()
.required()
.label("Folder")
};
async populateFolders() {
const { data: folders } = await getFolders();
this.setState({ folders });
}
async populateNote() {
try {
const noteId = this.props.match.params.id;
if (noteId === "new") return;
const { data: note } = await getNote(noteId);
this.setState({ data: this.mapToViewModel(note) });
} catch (ex) {
if (ex.response && ex.response.status === 404)
this.props.history.replace("/not-found");
}
}
async componentDidMount() {
await this.populateFolders();
await this.populateNote();
}
mapToViewModel(note) {
return {
_id: note._id,
title: note.title,
content: note.content,
folderId: note.folder._id
};
}
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
doSubmit = async () => {
await saveNote(this.state.data);
};
render() {
return (
<div>
<h1>Add new note</h1>
<form onSubmit={this.handleSubmit}>
{this.renderSelect("folderId", "Folder", this.state.folders)}
{this.renderInput("title", "Title")}
{this.renderInput("content", "Content")}
{this.renderButton("Add")}
</form>
</div>
);
}
}
export default NewNoteForm;
import React, { Component } from "react";
import { getNotes, deleteNote } from "../services/noteService";
import ListGroup from "./common/listGroup";
import { getFolders } from "../services/folderService";
import { toast } from "react-toastify";
import SingleNote from "./singleNote";
import NewNoteForm from "./newNoteForm";
class Notes extends Component {
state = {
notes: [], //I initialize them here so they are not undefined while componentDidMount is rendering them, otherwise I'd get a runtime error
folders: [],
selectedFolder: null
};
async componentDidMount() {
const { data } = await getFolders();
const folders = [{ _id: "", name: "All notes" }, ...data];
const { data: notes } = await getNotes();
this.setState({ notes, folders });
}
handleDelete = async note => {
const originalNotes = this.state.notes;
const notes = originalNotes.filter(n => n._id !== note._id);
this.setState({ notes });
try {
await deleteNote(note._id);
} catch (ex) {
if (ex.response && ex.response.status === 404)
toast.error("This note has already been deleted.");
this.setState({ notes: originalNotes });
}
};
handleFolderSelect = folder => {
this.setState({ selectedFolder: folder }); //here I say that this is a selected folder
};
render() {
const { selectedFolder, notes } = this.state;
const filteredNotes =
selectedFolder && selectedFolder._id //if the selected folder is truthy I get all the notes with this folder id, otherwise I get all the notes
? notes.filter(n => n.folder._id === selectedFolder._id)
: notes;
return (
<div className="row m-0">
<div className="col-3">
<ListGroup
items={this.state.folders}
selectedItem={this.state.selectedFolder} //here I say that this is a selected folder
onItemSelect={this.handleFolderSelect}
/>
</div>
<div className="col">
<SingleNote
filteredNotes={filteredNotes}
onDelete={this.handleDelete}
/>
<NewNoteForm />
</div>
</div>
);
}
}
export default Notes;
doSubmit/handleSubmit = async (event) => {
event.preventDefault();
event.stopPropagation();
const newNote = await saveNote(this.state.data);
this.props.onNewNoteCreated(newNote);
}
您可能希望在提交处理程序()中使用
event.preventDefault()
和event.stopPropagation()
,停止表单提交页面的刷新。,当然还有明显的redux/flux方法以及漂亮的图形和解释谢谢=)请注意,该图像不是我自己的,但是来自杰森·阿诺德的中间帖子:很好的解释,我以前甚至不知道该找什么,谢谢你帮我找到了正确的方向!