问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

怎么解决React中多个组件间的事件传递

发布网友 发布时间:2022-04-22 19:38

我来回答

2个回答

懂视网 时间:2022-04-20 14:05

这篇文章给大家介绍的内容是关于React中跨组件分发状态的三种方法介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

当我问自己第一百次时,我正在研究一个典型的CRUD屏幕:“我应该将状态保留在这个组件中还是将其移动到父组件?”。

如果需要对子组件的状态进行轻微控制。您可能也遇到了同样的问题。

让我们通过一个简单的例子和三种修复方法来回顾它。前两种方法是常见的做法,第三种方法不太常规。

问题;

为了向您展示我的意思,我将使用一个简单的书籍CRUD(译者注:增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete))屏幕(如此简单,它没有创建和删除操作)。

381280250-5b6ae9839a548_articlex.png

我们有三个组成部分。<BookList />是一个组件,显示了用于编辑它们的书籍和按钮列表。<BookForm />有两个输入和一个按钮,用于保存对书籍的更改。以及包含其他两个组件的<BookApp />。

那么,我们的状态是什么?好吧,<BookApp />应该跟踪书籍清单以及识别当前正在编辑的书籍的内容。 <BookList />没有任何状态。并且<BookForm />应该保持输入的当前状态,直到单击“保存”按钮。

import React, { Component } from "react";
import { render } from "react-dom";

const books = [
 {
 title: "The End of Eternity",
 author: "Isaac Asimov"
 },
 //...
];

const BookList = ({ books, onEdit }) => (
 <table>
 <tr>
 <th>Book Title</th>
 <th>Actions</th>
 </tr>
 {books.map((book, index) => (
 <tr>
 <td>{book.title}</td>
 <td>
  <button onClick={() => onEdit(index)}>Edit</button>
 </td>
 </tr>
 ))}
 </table>
);

class BookForm extends Component {
 state = { ...this.props.book };
 render() {
 if (!this.props.book) return null;
 return (
 <form>
 <h3>Book</h3>
 <label>
  Title:
  <input
  value={this.state.title}
  onChange={e => this.setState({ title: e.target.value })}
  />
 </label>
 <label>
  Author:
  <input
  value={this.state.author}
  onChange={e => this.setState({ author: e.target.value })}
  />
 </label>
 <button onClick={() => this.props.onSave({ ...this.state })}>
  Save
 </button>
 </form>
 );
 }
}

class BookApp extends Component {
 state = {
 books: books,
 activeIndex: -1
 };
 render() {
 const { books, activeIndex } = this.state;
 const activeBook = books[activeIndex];
 return (
 <div>
 <BookList
  books={books}
  onEdit={index =>
  this.setState({
  activeIndex: index
  })}
 />
 <BookForm
  book={activeBook}
  onSave={book =>
  this.setState({
  books: Object.assign([...books], { [activeIndex]: book }),
  activeIndex: -1
  })}
 />
 </div>
 );
 }
}

render(<BookApp />, document.getElementById("root"));

在codesandbox尝试一下

看起来不错,但是他不起作用。

我们正在创建组件实例时初始化<BookForm />状态,因此,当从列表中选择另一本书时,父级无法让它知道它需要更改它。

我们改如何修复它?

方法1:受控组件

一种常见的方法是将状态提升,将<BookForm />转换为受控组件。我们删除<BookForm />状态,将activeBook添加到<BookApp />状态,并向<BookForm />添加一个onChange道具,我们在每次输入时都会调用它。

//...

class BookForm extends Component {
 render() {
 if (!this.props.book) return null;
 return (
 <form>
 <h3>Book</h3>
 <label>
  Title:
  <input
  value={this.props.book.title}
  onChange={e =>
  this.props.onChange({
  ...this.props.book,
  title: e.target.value
  })}
  />
 </label>
 <label>
  Author:
  <input
  value={this.props.book.author}
  onChange={e =>
  this.props.onChange({
  ...this.props.book,
  author: e.target.value
  })}
  />
 </label>
 <button onClick={() => this.props.onSave()}>Save</button>
 </form>
 );
 }
}

class BookApp extends Component {
 state = {
 books: books,
 activeBook: null,
 activeIndex: -1
 };
 render() {
 const { books, activeBook, activeIndex } = this.state;
 return (
 <div>
 <BookList
  books={books}
  onEdit={index =>
  this.setState({
  activeBook: { ...books[index] },
  activeIndex: index
  })}
 />
 <BookForm
  book={activeBook}
  onChange={book => this.setState({ activeBook: book })}
  onSave={() =>
  this.setState({
  books: Object.assign([...books], { [activeIndex]: activeBook }),
  activeBook: null,
  activeIndex: -1
  })}
 />
 </div>
 );
 }
}

//...

方法2:同步state

现在它可以工作,但对我来说,提升<BookForm />的状态感觉不对。在用户单击“保存”之前,<BookApp />不关心对书的任何更改,那么为什么需要将其保持在自己的状态?

在codesandbox尝试一下

现在它可以工作,但对我来说,提升<BookForm />的状态感觉不对。在用户单击“保存”之前,<BookApp />不关心对书的任何更改,那么为什么需要将其保持在自己的状态?

//...
class BookForm extends Component {
 state = { ...this.props.book };
 componentWillReceiveProps(nextProps) {
 const nextBook = nextProps.book;
 if (this.props.book !== nextBook) {
 this.setState({ ...nextBook });
 }
 }
 render() {
 if (!this.props.book) return null;
 return (
 <form>
 <h3>Book</h3>
 <label>
  Title:
  <input
  value={this.state.title}
  onChange={e => this.setState({ title: e.target.value })}
  />
 </label>
 <label>
  Author:
  <input
  value={this.state.author}
  onChange={e => this.setState({ author: e.target.value })}
  />
 </label>
 <button onClick={() => this.props.onSave({ ...this.state })}>
  Save
 </button>
 </form>
 );
 }
}
//...

在codesandbox尝试一下

这种方法通常被认为是一种不好的做法,因为它违背了React关于拥有单一事实来源的想法。我不确定是这种情况,然而,同步状态并不总是那么容易。此外,我尽量避免使用生命周期方法。

方法3:由Key控制的组件

但为什么我们要回收旧的状态呢?每次用户选择一本书时,拥有一个全新状态的新实例是不是有意义?

为此,我们需要告诉React停止使用旧实例并创建一个新实例。这就是key prop的用途。

//...
class BookApp extends Component {
 state = {
books: books,
activeIndex: -1
};
 render() {
const { books, activeIndex } = this.state;
const activeBook = books[activeIndex];
return (
 <div>
 <BookList
 books={books}
 onEdit={index =>
 this.setState({
  activeIndex: index
 })}
 />
 <BookForm
 key={activeIndex}
 book={activeBook}
 onSave={book =>
 this.setState({
  books: Object.assign([...books], { [activeIndex]: book }),
  activeIndex: -1
 })}
 />
 </div>
);
}
}
//...

在codesandbox尝试一下。

如果元素具有与上一个渲染不同的键,则React会为其创建一个新实例。因此,当用户选择新书时,<BookForm />的键更改,将创建组件的新实例,并从props初始化状态。

相关文章推荐:

React Native跨域资源加载出错如何解决

React-JSX中如何实现Class与Style的动态绑定(附实例)

热心网友 时间:2022-04-20 11:13

在js中 require失败的问题,大多数是require的那个东西(实际就是一个js文件),并没有部署在当前的node服务器里,所以解决办法就是把那个js文件手动copy一份到启动react-js的node服务器目录下
npm install -g 中-g是globel的意思
require 寻找顺序是依次寻找上级目录

可以通过react-native android在当前目录下创建一个包括rn骨架的工程
默认引用index.android.js

直接自定义使用也是不行的
Command`run-myReactAndroid` unrecognized Usage:react-native
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
如何在win10下安装docker? windows(win10)上的docker使用:安装(国内镜像)、操作 win10安装dockerWin10下Docker安装和使用 关于安装配置docker,找不到Hyper-V(win10 家庭版需要配置,专业版不需要... 怎么把微信上的聊天记录转到新手机 怎么把聊天记录转到另一个手机 快递被别人冒领,快递公司有没有责任 洋葱汤洋葱汤 一颗洋葱汤怎么做 一颗洋葱汤怎么做好吃 姜汁松花蛋窍门 姜汁松花蛋的汁怎么调 松花蛋姜汁松花蛋怎么做 react 箭头函数 可以把this当参数吗 姜汁皮蛋有什么做法? react 这样的写法怎么使用this.state this.setState? 姜汁松花蛋怎么调汁 react中这几种定义函数的方式,有什么区别 姜汁松花蛋的做法有哪些? React Native中的this,怎么理解 姜汁松花蛋怎么做如何做好吃 如何测试react中的this.state 姜汁松花蛋的做法汁 React组件方法中为什么要绑定this 姜汁松花蛋怎么做? react子组件this.props.xxx返回undefined 姜汁松花蛋的做法 苹果6怎么重设ID密码呢? 金针菇炒牛肉的做法 金针菇炒牛肉怎么做 西红柿和金针菇能一起吃吗 React中如何优雅的捕捉事件错误 小米手机突然耗电很快 姜汁松花蛋怎么做? this.refs undefined怎么解决 姜汁松花蛋的做法 松花蛋拌豆腐的做法 proptypes 在react中不能用为什么 姜汁皮蛋怎么做 姜汁皮蛋咋做 的做法,姜汁松花蛋怎么做好吃,姜汁松花蛋的家常做法 松花蛋姜汁怎么做好吃 姜汁松花蛋怎么做好吃 凉菜 宋慧乔最新韩剧 《太阳的后羿》中宋慧乔扮演的角色? 宋慧乔有五部经典电视剧,《太阳的后裔》只能排第四,第一是哪部? 宋慧乔演过哪些韩剧? 宋慧乔的新剧叫什么名字 想找宋慧乔演的韩剧~~ 宋慧乔演过哪些韩剧啊! 韩剧宋慧乔在剧中饰演瞎子的电视剧 四川红烧排骨的做法最正宗的做法