Reactクラスコンポーネントの状態を管理する方法
著者は、 Creative Commons を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
React では、 state は、アプリケーション内でデータが時間の経過とともにどのように変化するかを追跡する構造を指します。 状態の管理は、インタラクティブなコンポーネントや動的なWebアプリケーションを作成できるため、Reactの重要なスキルです。 状態は、フォーム入力の追跡からAPIからの動的データのキャプチャまですべてに使用されます。 このチュートリアルでは、クラスベースのコンポーネントで状態を管理する例を実行します。
このチュートリアルの執筆時点で、公式の Reactドキュメントは、開発者が新しいコードを作成するときに、機能コンポーネントを使用するのではなく、Reactフックを採用して状態を管理することを推奨しています。 クラスベースのコンポーネント。 React Hooksの使用はより現代的な方法と考えられていますが、クラスベースのコンポーネントの状態を管理する方法を理解することも重要です。 状態管理の背後にある概念を学ぶことは、既存のコードベースでクラスベースの状態管理をナビゲートおよびトラブルシューティングするのに役立ち、クラスベースの状態管理がより適切である場合を決定するのに役立ちます。 componentDidCatch と呼ばれるクラスベースのメソッドもありますが、これはフックでは使用できず、クラスメソッドを使用して状態を設定する必要があります。
このチュートリアルでは、最初に静的な値を使用して状態を設定する方法を示します。これは、古い値をオーバーライドするAPIからのデータの設定など、次の状態が最初の状態に依存しない場合に役立ちます。 次に、状態を現在の状態として設定する方法について説明します。これは、値の切り替えなど、次の状態が現在の状態に依存する場合に役立ちます。 状態を設定するこれらのさまざまな方法を調べるために、オプションのリストから購入を追加することによって更新する製品ページコンポーネントを作成します。
前提条件
-
Node.jsを実行する開発環境が必要になります。 このチュートリアルは、Node.jsバージョン10.20.1およびnpmバージョン6.14.4でテストされました。 これをmacOSまたはUbuntu18.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはの
PPAを使用したインストール ]セクションの手順に従います。 Ubuntu18.04にNode.jsをインストールする方法。 -
このチュートリアルでは、 Create ReactAppを使用してアプリを作成します。 Create React Appを使用してアプリケーションをインストールする手順については、 Create ReactAppを使用してReactプロジェクトをセットアップする方法を参照してください。
-
また、 JavaScriptでコーディングする方法にあるJavaScriptの基本的な知識と、HTMLおよびCSSの基本的な知識も必要です。 HTMLとCSSの優れたリソースは、 Mozilla DeveloperNetworkです。
ステップ1—空のプロジェクトを作成する
このステップでは、 Create ReactAppを使用して新しいプロジェクトを作成します。 次に、プロジェクトをブートストラップするときにインストールされるサンプルプロジェクトと関連ファイルを削除します。 最後に、コンポーネントを整理するための単純なファイル構造を作成します。 これにより、クラスベースのコンポーネントの状態を管理するためのこのチュートリアルのサンプルアプリケーションを構築するための強固な基盤が得られます。
まず、新しいプロジェクトを作成します。 ターミナルで次のスクリプトを実行して、を使用して新しいプロジェクトをインストールします create-react-app
:
- npx create-react-app state-class-tutorial
プロジェクトが終了したら、次のディレクトリに移動します。
- cd state-class-tutorial
新しいターミナルタブまたはウィンドウで、 CreateReactApp開始スクリプトを使用してプロジェクトを開始します。 ブラウザは変更時に自動更新されるため、作業中はこのスクリプトを実行したままにします。
- npm start
実行中のローカルサーバーを取得します。 プロジェクトがブラウザウィンドウで開かなかった場合は、 http:// localhost:3000/でプロジェクトを開くことができます。 これをリモートサーバーから実行している場合、アドレスは次のようになります。 http://your_domain:3000
.
ブラウザには、CreateReactAppの一部として含まれている単純なReactアプリケーションが読み込まれます。
完全に新しいカスタムコンポーネントのセットを構築するので、空のプロジェクトを作成できるように、ボイラープレートコードをクリアすることから始める必要があります。
開始するには、 src/App.js
テキストエディタで。 これは、ページに挿入されるルートコンポーネントです。 すべてのコンポーネントはここから始まります。 あなたはについてのより多くの情報を見つけることができます App.js
Create ReactAppを使用してReactプロジェクトを設定する方法。
開ける src/App.js
次のコマンドを使用します。
- nano src/App.js
次のようなファイルが表示されます。
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
行を削除します import logo from './logo.svg';
. 次に、のすべてを置き換えます return
空のタグのセットを返すステートメント: <></>
. これにより、何も返さない有効なページが表示されます。 最終的なコードは次のようになります。
import React from 'react';
import './App.css';
function App() {
return <></>;
}
export default App;
テキストエディタを保存して終了します。
最後に、ロゴを削除します。 アプリケーションで使用することはないので、作業中に未使用のファイルを削除する必要があります。 長期的には混乱からあなたを救うでしょう。
ターミナルウィンドウで、次のコマンドを入力します。
- rm src/logo.svg
ブラウザを見ると、空白の画面が表示されます。
サンプルのCreateReactAppプロジェクトをクリアしたので、単純なファイル構造を作成します。 これにより、コンポーネントを分離して独立させることができます。
と呼ばれるディレクトリを作成します components
の中に src
ディレクトリ。 これにより、すべてのカスタムコンポーネントが保持されます。
- mkdir src/components
各コンポーネントには、スタイル、画像、テストとともにコンポーネントファイルを保存するための独自のディレクトリがあります。
のディレクトリを作成します App
:
- mkdir src/components/App
すべてを移動します App
そのディレクトリにファイル。 ワイルドカードを使用して、 *
、で始まるファイルを選択します App.
ファイル拡張子に関係なく。 次に、 mv
それらを新しいディレクトリに配置するコマンド:
- mv src/App.* src/components/App
次に、で相対インポートパスを更新します index.js
、これはプロセス全体をブートストラップするルートコンポーネントです。
- nano src/index.js
importステートメントは、 App.js
のファイル App
ディレクトリなので、次の強調表示された変更を行います。
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App/App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
ファイルを保存して終了します。
プロジェクトが設定されたので、最初のコンポーネントを作成できます。
ステップ2—コンポーネントでの状態の使用
このステップでは、コンポーネントの初期状態をそのクラスに設定し、その状態を参照して値を表示します。 次に、状態値を使用してカート内の合計アイテムを表示するショッピングカートを使用して製品ページを作成します。 ステップの終わりまでに、値を保持するさまざまな方法と、小道具や静的な値ではなく状態を使用する必要がある場合を理解できます。
コンポーネントの構築
のディレクトリを作成することから始めます Product
:
- mkdir src/components/Product
次に、開きます Product.js
そのディレクトリ内:
- nano src/components/Product/Product.js
状態のないコンポーネントを作成することから始めます。 コンポーネントには2つの部分があります。アイテムの数と合計価格が表示されるカートと、アイテムを追加および削除するためのボタンが表示される製品です。 今のところ、ボタンにはアクションがありません。
次のコードをに追加します Product.js
:
import React, { Component } from 'react';
import './Product.css';
export default class Product extends Component {
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: 0 total items.
</div>
<div>Total: 0</div>
<div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
<button>Add</button> <button>Remove</button>
</div>
)
}
}
あなたはまた、いくつかを含めました div
JSX クラス名を持つ要素。これにより、基本的なスタイルを追加できます。
ファイルを保存して閉じてから、開きます Product.css
:
- nano src/components/Product/Product.css
軽いスタイリングを加えて、 font-size
テキストと絵文字の場合:
.product span {
font-size: 100px;
}
.wrapper {
padding: 20px;
font-size: 20px;
}
.wrapper button {
font-size: 20px;
background: none;
}
この例では絵文字が製品画像として機能するため、絵文字にはテキストよりもはるかに大きなフォントサイズが必要になります。 さらに、ボタンのデフォルトのグラデーションの背景を削除するには、 background
に none
.
ファイルを保存して閉じます。
今、レンダリングします Product
のコンポーネント App
コンポーネントを使用して、ブラウザで結果を確認できます。 開ける App.js
:
- nano src/components/App/App.js
コンポーネントをインポートしてレンダリングします。 このチュートリアルでは使用しないため、CSSインポートを削除することもできます。
import React from 'react';
import Product from '../Product/Product';
function App() {
return <Product />
}
export default App;
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、次のように表示されます。 Product
成分。
クラスコンポーネントの初期状態の設定
表示で変更されるコンポーネント値には、アイテムの総数とコストの2つの値があります。 それらをハードコーディングする代わりに、このステップでは、それらをオブジェクトと呼ばれるものに移動します。 state
.
The state
Reactクラスのは、ページのレンダリングを制御する特別なプロパティです。 状態を変更すると、Reactはコンポーネントが古くなっていることを認識し、自動的に再レンダリングします。 コンポーネントが再レンダリングされると、レンダリングされた出力が変更され、最新の情報が含まれるようになります。 state
. この例では、商品をカートに追加したり、カートから削除したりするたびに、コンポーネントが再レンダリングされます。 Reactクラスに他のプロパティを追加することはできますが、それらには再レンダリングをトリガーする同じ機能はありません。
開ける Product.js
:
- nano src/components/Product/Product.js
というプロパティを追加します state
に Product
クラス。 次に、2つの値をに追加します state
物体: cart
と total
. The cart
最終的に多くのアイテムを保持する可能性があるため、配列になります。 The total
数字になります。 これらを割り当てた後、値への参照を次のように置き換えます this.state.property
:
import React, { Component } from 'react';
import './Product.css';
export default class Product extends Component {
state = {
cart: [],
total: 0
}
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: {this.state.cart.length} total items.
</div>
<div>Total {this.state.total}</div>
<div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
<button>Add</button> <button>Remove</button>
</div>
)
}
}
どちらの場合も、JSX内でJavaScriptを参照しているため、コードを中括弧で囲む必要があることに注意してください。 また、を表示しています length
の cart
配列内のアイテム数のカウントを取得するための配列。
ファイルを保存します。 これを行うと、ブラウザが更新され、以前と同じページが表示されます。
The state
プロパティは標準クラスのプロパティです。つまり、プロパティだけでなく、他のメソッドでもアクセスできます。 render
方法。
次に、価格を静的な値として表示する代わりに、 toLocaleString メソッドを使用して文字列に変換します。これにより、ブラウザの領域での数値の表示方法に一致する文字列に数値が変換されます。
と呼ばれるメソッドを作成します getTotal()
それはかかります state
の配列を使用してローカライズされた文字列に変換します currencyOptions
. 次に、への参照を置き換えます state
JSXでメソッド呼び出しを使用して:
import React, { Component } from 'react';
import './Product.css';
export default class Product extends Component {
state = {
cart: [],
total: 0
}
currencyOptions = {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}
getTotal = () => {
return this.state.total.toLocaleString(undefined, this.currencyOptions)
}
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: {this.state.cart.length} total items.
</div>
<div>Total {this.getTotal()}</div>
<div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
<button>Add</button> <button>Remove</button>
</div>
)
}
}
以来 total
商品の価格です、あなたは通過しています currencyOptions
小数点以下の最大値と最小値を設定します total
2つに。 これは別のプロパティとして設定されていることに注意してください。 多くの場合、初心者のReact開発者は、このような情報を state
オブジェクトですが、情報を追加するのは state
あなたが変えることを期待していること。 このように、の情報 state
アプリケーションの規模が拡大するにつれて、追跡が容易になります。
あなたが行ったもう1つの重要な変更は、 getTotal()
矢印関数をクラスプロパティに割り当てることによるメソッド。 矢印関数を使用しない場合、このメソッドは新しいこのバインディングを作成し、現在の this
バインドして、コードにバグを導入します。 これについては、次のステップで詳しく説明します。
ファイルを保存します。 これを行うと、ページが更新され、値が小数に変換されて表示されます。
これで、コンポーネントに状態が追加され、クラスで参照されました。 また、の値にアクセスしました render
メソッドおよび他のクラスのメソッド。 次に、状態を更新して動的な値を表示するメソッドを作成します。
ステップ3—静的な値から状態を設定する
これまで、コンポーネントの基本状態を作成し、関数とJSXコードでその状態を参照しました。 このステップでは、製品ページを更新して、 state
ボタンのクリックで。 更新された値を含む新しいオブジェクトを、という特別なメソッドに渡す方法を学習します。 setState
、次に設定します state
更新されたデータで。
更新するには state
、React開発者はと呼ばれる特別な方法を使用します setState
それはベースから継承されます Component
クラス。 The setState
メソッドは、最初の引数としてオブジェクトまたは関数のいずれかを取ることができます。 参照する必要のない静的な値がある場合 state
、読みやすいので、新しい値を含むオブジェクトを渡すのが最善です。 現在の状態を参照する必要がある場合は、古いものへの参照を回避するための関数を渡します state
.
ボタンにイベントを追加することから始めます。 ユーザーが追加をクリックすると、プログラムはアイテムをに追加します cart
を更新します total
. 削除をクリックすると、カートが空のアレイにリセットされ、 total
に 0
. たとえば、プログラムでは、ユーザーがアイテムを2回以上追加することはできません。
開ける Product.js
:
- nano src/components/Product/Product.js
コンポーネント内で、という新しいメソッドを作成します add
、次にメソッドをに渡します onClick
追加ボタンの小道具:
import React, { Component } from 'react';
import './Product.css';
export default class Product extends Component {
state = {
cart: [],
total: 0
}
add = () => {
this.setState({
cart: ['ice cream'],
total: 5
})
}
currencyOptions = {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}
getTotal = () => {
return this.state.total.toLocaleString(undefined, this.currencyOptions)
}
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: {this.state.cart.length} total items.
</div>
<div>Total {this.getTotal()}</div>
<div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
<button onClick={this.add}>Add</button>
<button>Remove</button>
</div>
)
}
}
内部 add
メソッド、あなたは setState
メソッドを実行し、更新されたオブジェクトを含むオブジェクトを渡します cart
単一のアイテムで ice cream
との更新された価格 5
. 再び矢印関数を使用して作成したことに注意してください。 add
方法。 前に述べたように、これは関数が適切であることを保証します this
更新を実行するときのコンテキスト。 矢印関数を使用せずにメソッドとして関数を追加すると、 setState
関数を現在のコンテキストにバインディングしないと存在しません。
たとえば、 add
このように機能します:
export default class Product extends Component {
...
add() {
this.setState({
cart: ['ice cream'],
total: 5
})
}
...
}
追加ボタンをクリックするとエラーが発生します。
矢印関数を使用すると、このエラーを回避するための適切なコンテキストを確保できます。
ファイルを保存します。 これを行うと、ブラウザがリロードされ、追加ボタンをクリックすると、カートが現在の金額で更新されます。
とともに add
メソッド、あなたはの両方のプロパティを渡しました state
物体: cart
と total
. ただし、必ずしも完全なオブジェクトを渡す必要はありません。 更新するプロパティを含むオブジェクトを渡すだけで、他のすべては同じままになります。
Reactが小さなオブジェクトをどのように処理できるかを確認するには、という新しい関数を作成します。 remove
. だけを含む新しいオブジェクトを渡します cart
空の配列を使用して、メソッドをに追加します onClick
削除ボタンのプロパティ:
import React, { Component } from 'react';
import './Product.css';
export default class Product extends Component {
...
remove = () => {
this.setState({
cart: []
})
}
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: {this.state.cart.length} total items.
</div>
<div>Total {this.getTotal()}</div>
<div className="product"><span role="img" aria-label="ice cream">🍦</span></div>
<button onClick={this.add}>Add</button>
<button onClick={this.remove}>Remove</button>
</div>
)
}
}
ファイルを保存します。 ブラウザが更新されたら、追加ボタンと削除ボタンをクリックします。 カートの更新は表示されますが、価格は表示されません。 The total
状態値は更新中に保持されます。 この値は、例としてのみ保持されます。 このアプリケーションでは、の両方のプロパティを更新する必要があります state
物体。 ただし、多くの場合、異なる責任を持つステートフルプロパティを持つコンポーネントがあり、更新されたオブジェクトからそれらを除外することで、それらを永続化できます。
このステップでの変更は静的でした。 事前に値がどうなるかを正確に知っていたので、から再計算する必要はありませんでした。 state
. ただし、商品ページに多数の商品があり、それらを複数回追加できるようにしたい場合は、静的オブジェクトを渡しても、最新の商品を参照する保証はありません。 state
、オブジェクトが使用した場合でも this.state
価値。 この場合、代わりに関数を使用できます。
次のステップでは、更新します state
現在の状態を参照する関数を使用します。
ステップ4—現在の状態を使用して状態を設定する
配列の更新、数値の追加、オブジェクトの変更など、現在の状態を更新するために以前の状態を参照する必要がある場合がよくあります。 できるだけ正確にするには、最新のものを参照する必要があります state
物体。 更新とは異なり state
事前定義された値を使用して、このステップで関数をに渡します setState
メソッド。現在の状態を引数として取ります。 このメソッドを使用して、現在の状態を使用してコンポーネントの状態を更新します。
設定のもう1つの利点 state
機能を備えているので、信頼性が向上します。 パフォーマンスを向上させるために、Reactはバッチ処理する場合があります setState
呼び出し、つまり this.state.value
完全に信頼できるとは限りません。 たとえば、更新する場合 state
いくつかの場所ですぐに、値が古くなっている可能性があります。 これは、データのフェッチ、フォームの検証、または複数のアクションが並行して発生している状況で発生する可能性があります。 ただし、最新の機能を使用する state
引数として、このバグがコードに入らないようにします。
この形式の状態管理を示すために、製品ページにさらにいくつかの項目を追加します。 まず、 Product.js
ファイル:
- nano src/components/Product/Product.js
次に、さまざまな製品のオブジェクトの配列を作成します。 配列には、商品の絵文字、名前、価格が含まれます。 次に、アレイをループして、追加および削除ボタンで各製品を表示します。
import React, { Component } from 'react';
import './Product.css';
const products = [
{
emoji: '🍦',
name: 'ice cream',
price: 5
},
{
emoji: '🍩',
name: 'donuts',
price: 2.5,
},
{
emoji: '🍉',
name: 'watermelon',
price: 4
}
];
export default class Product extends Component {
...
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: {this.state.cart.length} total items.
</div>
<div>Total {this.getTotal()}</div>
<div>
{products.map(product => (
<div key={product.name}>
<div className="product">
<span role="img" aria-label={product.name}>{product.emoji}</span>
</div>
<button onClick={this.add}>Add</button>
<button onClick={this.remove}>Remove</button>
</div>
))}
</div>
</div>
)
}
}
このコードでは、 map()配列メソッドを使用してループします。 products
ブラウザに各要素を表示するJSXを配列して返します。
ファイルを保存します。 ブラウザがリロードされると、更新された製品リストが表示されます。
次に、メソッドを更新する必要があります。 まず、 add()
取る方法 product
引数として。 次に、オブジェクトをに渡す代わりに setState()
、を受け取る関数を渡します state
引数として、 cart
新製品と total
新しい価格で更新:
import React, { Component } from 'react';
import './Product.css';
...
export default class Product extends Component {
state = {
cart: [],
total: 0
}
add = (product) => {
this.setState(state => ({
cart: [...state.cart, product.name],
total: state.total + product.price
}))
}
currencyOptions = {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}
getTotal = () => {
return this.state.total.toLocaleString(undefined, this.currencyOptions)
}
remove = () => {
this.setState({
cart: []
})
}
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: {this.state.cart.length} total items.
</div>
<div>Total {this.getTotal()}</div>
<div>
{products.map(product => (
<div key={product.name}>
<div className="product">
<span role="img" aria-label={product.name}>{product.emoji}</span>
</div>
<button onClick={() => this.add(product)}>Add</button>
<button onClick={this.remove}>Remove</button>
</div>
))}
</div>
</div>
)
}
}
渡す匿名関数の内部 setState()
、必ず引数を参照してください—state
—コンポーネントの状態ではありません—this.state
. そうしないと、古くなるリスクがあります state
物体。 The state
関数内はそれ以外は同じになります。
状態を直接変更しないように注意してください。 代わりに、に新しい値を追加するとき cart
、新しいを追加できます product
に state
現在の値にspread構文を使用し、最後に新しい値を追加します。
最後に、呼び出しを更新します this.add
を変更することによって onClick()
を呼び出す無名関数を取るための小道具 this.add()
関連する製品と。
ファイルを保存します。 これを行うと、ブラウザがリロードされ、複数の製品を追加できるようになります。
次に、を更新します remove()
方法。 同じ手順に従います:変換 setState
関数を取得するには、変更せずに値を更新し、 onChange()
小道具:
import React, { Component } from 'react';
import './Product.css';
...
export default class Product extends Component {
...
remove = (product) => {
this.setState(state => {
const cart = [...state.cart];
cart.splice(cart.indexOf(product.name))
return ({
cart,
total: state.total - product.price
})
})
}
render() {
return(
<div className="wrapper">
<div>
Shopping Cart: {this.state.cart.length} total items.
</div>
<div>Total {this.getTotal()}</div>
<div>
{products.map(product => (
<div key={product.name}>
<div className="product">
<span role="img" aria-label={product.name}>{product.emoji}</span>
</div>
<button onClick={() => this.add(product)}>Add</button>
<button onClick={() => this.remove(product)}>Remove</button>
</div>
))}
</div>
</div>
)
}
}
状態オブジェクトの変更を回避するには、最初にを使用してそのコピーを作成する必要があります。 spread
オペレーター。 次に、コピーから必要なアイテムをスプライスして、新しいオブジェクトにコピーを返すことができます。 コピーすることによって state
最初のステップとして、あなたはあなたが変異しないことを確信することができます state
物体。
ファイルを保存します。 これを行うと、ブラウザが更新され、アイテムを追加および削除できるようになります。
このアプリケーションにはまだバグがあります。 remove
メソッドでは、ユーザーはから減算することができます total
アイテムが含まれていない場合でも cart
. カートに追加せずにアイスクリームの削除をクリックすると、合計は-5.00になります。
減算する前にアイテムの存在を確認することでバグを修正できますが、より簡単な方法は、製品への参照のみを保持し、製品への参照と合計コストを分離しないことで、状態オブジェクトを小さく保つことです。 同じデータへの二重参照を避けるようにしてください。 代わりに、生データをに保存します state
—この場合、全体 product
オブジェクト-次に、外部で計算を実行します state
.
コンポーネントをリファクタリングして、 add()
メソッドはオブジェクト全体を追加します remove()
メソッドはオブジェクト全体を削除し、 getTotal
メソッドはを使用します cart
:
import React, { Component } from 'react';
import './Product.css';
...
export default class Product extends Component {
state = {
cart: [],
}
add = (product) => {
this.setState(state => ({
cart: [...state.cart, product],
}))
}
currencyOptions = {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}
getTotal = () => {
const total = this.state.cart.reduce((totalCost, item) => totalCost + item.price, 0);
return total.toLocaleString(undefined, this.currencyOptions)
}
remove = (product) => {
this.setState(state => {
const cart = [...state.cart];
const productIndex = cart.findIndex(p => p.name === product.name);
if(productIndex < 0) {
return;
}
cart.splice(productIndex, 1)
return ({
cart
})
})
}
render() {
...
}
}
The add()
メソッドは以前と似ていますが、 total
プロパティは削除されました。 の中に remove()
メソッド、あなたはのインデックスを見つけます product
と findByIndex
. インデックスが存在しない場合は、 -1
. その場合、条件文を使用して何も返しません。 何も返さないことで、Reactは state
変更されず、再レンダリングをトリガーしません。 戻ったら state
または空のオブジェクトでも、再レンダリングがトリガーされます。
使用する場合 splice()
メソッド、あなたは今合格しています 1
2番目の引数として、1つの値を削除し、残りを保持します。
最後に、 total
reduce()配列メソッドを使用します。
ファイルを保存します。 これを行うと、ブラウザが更新され、最終版が作成されます cart
:
The setState
渡す関数には、現在の小道具の追加の引数を含めることができます。これは、現在の小道具を参照する必要がある状態がある場合に役立ちます。 コールバック関数をに渡すこともできます setState
最初の引数にオブジェクトまたは関数を渡すかどうかに関係なく、2番目の引数として。 これは、設定するときに特に便利です state
APIからデータをフェッチした後、その後に新しいアクションを実行する必要があります state
更新が完了しました。
このステップでは、現在の状態に基づいて新しい状態を更新する方法を学習しました。 関数をに渡しました setState
関数と現在の状態を変更せずに計算された新しい値。 また、終了する方法を学びました setState
再レンダリングを妨げるような方法で更新がない場合に機能し、パフォーマンスがわずかに向上します。
結論
このチュートリアルでは、静的に更新し、現在の状態を使用する動的な状態を持つクラスベースのコンポーネントを開発しました。 これで、ユーザーと動的な情報に対応する複雑なプロジェクトを作成するためのツールが手に入りました。
Reactにはフックを使用して状態を管理する方法がありますが、クラスベースである必要があるコンポーネント(たとえば、 componentDidCatch
方法。
状態の管理は、ほぼすべてのコンポーネントにとって重要であり、インタラクティブなアプリケーションを作成するために必要です。 この知識があれば、スライダー、アコーディオン、フォームなど、多くの一般的なWebコンポーネントを再作成できます。 次に、フックを使用してアプリケーションを構築したり、APIから動的にデータをプルするコンポーネントを開発したりするのと同じ概念を使用します。
Reactのチュートリアルをもっと見たい場合は、 Reactトピックページを確認するか、React.jsシリーズのコーディング方法ページに戻ってください。