目次
问题;
Book
方法1:受控组件
方法2:同步state
方法3:由Key控制的组件
ホームページ ウェブフロントエンド htmlチュートリアル React のコンポーネント間で状態を分散するための 3 つの方法の紹介

React のコンポーネント間で状態を分散するための 3 つの方法の紹介

Aug 09, 2018 pm 01:35 PM
css html javascript react.js

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

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

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

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

问题;

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

React のコンポーネント間で状態を分散するための 3 つの方法の紹介

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

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

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

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

const BookList = ({ books, onEdit }) => (
  
ログイン後にコピー
                            {books.map((book, index) => (                                     ))}   
Book TitleActions
{book.title}                    
); class BookForm extends Component {   state = { ...this.props.book };   render() {     if (!this.props.book) return null;     return (       
        

Book

                                 
    );   } } class BookApp extends Component {   state = {     books: books,     activeIndex: -1   };   render() {     const { books, activeIndex } = this.state;     const activeBook = books[activeIndex];     return (       
                     this.setState({               activeIndex: index             })}         />                      this.setState({               books: Object.assign([...books], { [activeIndex]: book }),               activeIndex: -1             })}         />       
    );   } } render(, document.getElementById("root"));

在codesandbox尝试一下

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

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

我们改如何修复它?

方法1:受控组件

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

//...

class BookForm extends Component {
  render() {
    if (!this.props.book) return null;
    return (
      <form>
        <h3 id="Book">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

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

在codesandbox尝试一下

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

//...
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 id="Book">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会为其创建一个新实例。因此,当用户选择新书时,的键更改,将创建组件的新实例,并从props初始化状态。

相关文章推荐:

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

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

以上がReact のコンポーネント間で状態を分散するための 3 つの方法の紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

VueでBootstrapの使用方法 VueでBootstrapの使用方法 Apr 07, 2025 pm 11:33 PM

vue.jsでBootstrapを使用すると、5つのステップに分かれています。ブートストラップをインストールします。 main.jsにブートストラップをインポートしますブートストラップコンポーネントをテンプレートで直接使用します。オプション:カスタムスタイル。オプション:プラグインを使用します。

HTML、CSS、およびJavaScriptの役割:コアの責任 HTML、CSS、およびJavaScriptの役割:コアの責任 Apr 08, 2025 pm 07:05 PM

HTMLはWeb構造を定義し、CSSはスタイルとレイアウトを担当し、JavaScriptは動的な相互作用を提供します。 3人はWeb開発で職務を遂行し、共同でカラフルなWebサイトを構築します。

ブートストラップにスプリットラインを書く方法 ブートストラップにスプリットラインを書く方法 Apr 07, 2025 pm 03:12 PM

ブートストラップスプリットラインを作成するには2つの方法があります。タグを使用して、水平方向のスプリットラインを作成します。 CSS Borderプロパティを使用して、カスタムスタイルのスプリットラインを作成します。

HTML、CSS、およびJavaScriptの理解:初心者向けガイド HTML、CSS、およびJavaScriptの理解:初心者向けガイド Apr 12, 2025 am 12:02 AM

webdevelopmentReliesOnhtml、css、andjavascript:1)htmlStructuresContent、2)cssStylesit、および3)Javascriptaddsinteractivity、形成、

ブートストラップボタンの使用方法 ブートストラップボタンの使用方法 Apr 07, 2025 pm 03:09 PM

ブートストラップボタンの使用方法は?ブートストラップCSSを導入してボタン要素を作成し、ブートストラップボタンクラスを追加してボタンテキストを追加します

ブートストラップのサイズを変更する方法 ブートストラップのサイズを変更する方法 Apr 07, 2025 pm 03:18 PM

Bootstrapの要素のサイズを調整するには、次のものを含むDimensionクラスを使用できます。

HTMLにおけるReactの役割:ユーザーエクスペリエンスの向上 HTMLにおけるReactの役割:ユーザーエクスペリエンスの向上 Apr 09, 2025 am 12:11 AM

ReactはJSXとHTMLを組み合わせてユーザーエクスペリエンスを向上させます。 1)JSXはHTMLを埋め込み、開発をより直感的にします。 2)仮想DOMメカニズムは、パフォーマンスを最適化し、DOM操作を削減します。 3)保守性を向上させるコンポーネントベースの管理UI。 4)国家管理とイベント処理は、インタラクティブ性を高めます。

ブートストラップのフレームワークをセットアップする方法 ブートストラップのフレームワークをセットアップする方法 Apr 07, 2025 pm 03:27 PM

Bootstrapフレームワークをセットアップするには、次の手順に従う必要があります。1。CDNを介してブートストラップファイルを参照してください。 2。独自のサーバーでファイルをダウンロードしてホストします。 3。HTMLにブートストラップファイルを含めます。 4.必要に応じてSASS/LESSをコンパイルします。 5。カスタムファイルをインポートします(オプション)。セットアップが完了したら、Bootstrapのグリッドシステム、コンポーネント、スタイルを使用して、レスポンシブWebサイトとアプリケーションを作成できます。

See all articles