Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在不刷新页面的情况下立即在React中显示提交的数据?_Javascript_Reactjs - Fatal编程技术网

Javascript 如何在不刷新页面的情况下立即在React中显示提交的数据?

Javascript 如何在不刷新页面的情况下立即在React中显示提交的数据?,javascript,reactjs,Javascript,Reactjs,我正在开发一个简单的笔记应用程序,我正在尝试在笔记列表的末尾添加新的笔记,然后立即看到添加的笔记。不幸的是,我只能通过刷新页面来完成。有没有更简单的方法 我知道改变状态通常会有所帮助,但我有两个独立的组件,我不知道如何以任何方式连接它们 因此,在NewNoteForm组件中,我有一个提交操作: doSubmit = async () => { await saveNote(this.state.data); }; 然后在主组件中,我只传递NewNoteForm组件 下面是

我正在开发一个简单的笔记应用程序,我正在尝试在笔记列表的末尾添加新的笔记,然后立即看到添加的笔记。不幸的是,我只能通过刷新页面来完成。有没有更简单的方法

我知道改变状态通常会有所帮助,但我有两个独立的组件,我不知道如何以任何方式连接它们

因此,在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方法以及漂亮的图形和解释谢谢=)请注意,该图像不是我自己的,但是来自杰森·阿诺德的中间帖子:很好的解释,我以前甚至不知道该找什么,谢谢你帮我找到了正确的方向!