亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

詳解在React中跨組件分發狀態的三種方法

2019-11-19 13:18:26
字體:
來源:轉載
供稿:網友

當我問自己第一百次時,我正在研究一個典型的CRUD屏幕:“我應該將狀態保留在這個組件中還是將其移動到父組件?”。

如果需要對子組件的狀態進行輕微控制。您可能也遇到了同樣的問題。

讓我們通過一個簡單的例子和​​三種修復方法來回顧它。前兩種方法是常見的做法,第三種方法不太常規。

問題;

為了向您展示我的意思,我將使用一個簡單的書籍CRUD(譯者注:增加(Create)、讀取查詢(Retrieve)、更新(Update)和刪除(Delete))屏幕(如此簡單,它沒有創建和刪除操作)。

我們有三個組成部分。 <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"));

看起來不錯,但是他不起作用。

我們正在創建組件實例時初始化<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>  ); }}//...

現在它可以工作,但對我來說,提升 <BookForm /> 的狀態感覺不對。在用戶單擊“保存”之前, <BookApp /> 不關心對書的任何更改,那么為什么需要將其保持在自己的狀態?

方法2:同步state

現在它可以工作,但對我來說,提升<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>  ); }}//...

這種方法通常被認為是一種不好的做法,因為它違背了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>  ); }}//...

如果元素具有與上一個渲染不同的鍵,則React會為其創建一個新實例。因此,當用戶選擇新書時,<BookForm />的鍵更改,將創建組件的新實例,并從props初始化狀態。

有什么收獲?重用組件實例意味著更少的DOM突變,這意味著更好的性能。因此,當我們強制React創建組件的新實例時,我們會為額外的DOM突變獲得一些開銷。但是對于這樣的情況,這種開銷是最小的,其中密鑰沒有變化太快而且組件不大。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情一级欧美精品| 精品国产91久久久久久老师| 国产精品视频白浆免费视频| 青青久久av北条麻妃黑人| 亚洲乱亚洲乱妇无码| 国产精品三级网站| 国产精品91在线观看| 国产精品视频久久久| 成人在线观看视频网站| 亚洲欧美日韩精品久久亚洲区| 午夜精品一区二区三区视频免费看| 曰本色欧美视频在线| 久久久久久久久久久国产| 亚洲国产日韩精品在线| 久久精品成人动漫| 色系列之999| 尤物yw午夜国产精品视频| 91免费精品国偷自产在线| 国产精品高清在线| 久久伊人免费视频| 欧美影院在线播放| 欧美激情亚洲另类| 欧美在线观看视频| 正在播放亚洲1区| 日韩极品精品视频免费观看| 欧美精品www在线观看| 日韩在线观看免费高清完整版| 国产成人免费av电影| 国产91色在线|免| 亚洲aaaaaa| 国内成人精品视频| 日韩有码在线观看| 成人在线视频福利| 欧美超级乱淫片喷水| 国产成人亚洲综合91精品| 亚洲黄色免费三级| 久久久国产成人精品| 国产精品久久久久久久9999| 欧美亚洲一区在线| 国产精品久久久久久久一区探花| 久久视频在线免费观看| 欧美大荫蒂xxx| 2020欧美日韩在线视频| 亚洲丝袜在线视频| 777777777亚洲妇女| 日韩中文在线观看| 中文字幕一区日韩电影| 欧美另类高清videos| 国产精品爽爽爽爽爽爽在线观看| 亚洲无限乱码一二三四麻| 在线电影中文日韩| 国产精品电影一区| 精品国产一区二区三区在线观看| 韩剧1988免费观看全集| 91国产精品91| 亚洲精品99久久久久| 在线日韩欧美视频| 777777777亚洲妇女| 精品国产31久久久久久| 国产精品亚洲美女av网站| 菠萝蜜影院一区二区免费| 欧美成人在线网站| 成人中心免费视频| 欧美成人一二三| 欧美日韩国产一区二区三区| 2019中文字幕免费视频| 欧美日韩国产成人在线观看| 国内精品免费午夜毛片| 91久久精品国产91性色| 久久精品91久久香蕉加勒比| 久久夜色精品国产欧美乱| 国产精品久久久av久久久| 欧美午夜美女看片| www亚洲欧美| 国产视频观看一区| 在线中文字幕日韩| 日韩欧美高清在线视频| 日韩精品福利网站| 欧美黑人性视频| 国产视频精品自拍| 久久九九全国免费精品观看| 国产精品视频白浆免费视频| 精品一区二区三区四区在线| 久久免费少妇高潮久久精品99| 久久人人爽人人| 国产一区二区三区欧美| 久久激情视频免费观看| 最近中文字幕mv在线一区二区三区四区| 91福利视频在线观看| 狠狠躁夜夜躁人人躁婷婷91| 日韩美女视频免费看| 97碰碰碰免费色视频| 欧美中文字幕在线观看| 国产不卡av在线免费观看| 亚洲天堂开心观看| 国产精品视频一区二区高潮| 亚洲色图校园春色| 中文字幕亚洲欧美| 高清一区二区三区四区五区| 在线观看欧美日韩| 亚洲国产天堂网精品网站| 亚洲aaa激情| 久久天天躁夜夜躁狠狠躁2022| 久久精品国产免费观看| 亚洲一区中文字幕在线观看| 亚洲四色影视在线观看| 久久久在线免费观看| 69**夜色精品国产69乱| 日韩三级影视基地| 91最新在线免费观看| 伊人精品在线观看| 在线观看欧美日韩| 亚洲精品视频久久| 国产一区二区丝袜高跟鞋图片| 午夜精品久久久久久久久久久久久| 韩国福利视频一区| 亚洲视频999| 国产成人91久久精品| 91精品国产九九九久久久亚洲| 国产999在线观看| 国产一区玩具在线观看| 日韩欧美在线播放| 国产97色在线|日韩| 欧美电影免费观看大全| 国产精品视频在线播放| 亚洲国产天堂久久综合网| 亚洲成人av在线播放| 亚洲国产高清福利视频| 国产成人综合精品| 狠狠躁天天躁日日躁欧美| 7m精品福利视频导航| 亚洲一区二区三区毛片| 亚洲欧美另类国产| 欧美一级成年大片在线观看| 青青草原成人在线视频| 中文国产亚洲喷潮| 国产精品吴梦梦| 欧美另类在线播放| 国产精品专区一| 欧美成人精品激情在线观看| 性金发美女69hd大尺寸| 亚洲国产欧美日韩精品| 91精品在线播放| 久久久成人精品| 91久久国产综合久久91精品网站| 亚洲石原莉奈一区二区在线观看| 精品成人久久av| 久久久视频在线| 久久精品国产91精品亚洲| 亚洲精品久久视频| 亚洲欧美综合区自拍另类| 美女扒开尿口让男人操亚洲视频网站| 国内免费精品永久在线视频| 日韩av有码在线| 久久久亚洲国产天美传媒修理工| 午夜精品视频在线| 欧美高清视频在线| 欧美色视频日本高清在线观看| 久久久久亚洲精品成人网小说| 欧美日本国产在线| 日韩欧美主播在线| 91美女高潮出水| 亚洲国产精品人久久电影| 亚洲国产精品一区二区三区|