インストール
モジュールをインストールします
npm install @wordpress/data --save
このパッケージは、あなたのコードがES2015+環境で実行されることを前提としています。もし、言語機能やAPIのサポートが限られているか、全くない環境を使用している場合は、コードに@wordpress/babel-preset-default
で提供されるポリフィルを含めるべきです。
ストアの登録
register
関数を使用して、独自のストアを中央データレジストリに追加します。この関数は1つの引数を受け取ります - createReduxStore
ファクトリ関数で作成できるストア記述子です。createReduxStore
は2つの引数を受け取ります:モジュールを識別するための名前と、状態がどのように表現され、変更され、アクセスされるかを説明する値を持つ構成オブジェクトです。最低限、状態の形状と、ストアにディスパッチされたアクションに応じてどのように変更されるかを説明するリデューサー関数を提供する必要があります。
import apiFetch from '@wordpress/api-fetch';
import { createReduxStore, register } from '@wordpress/data';
const DEFAULT_STATE = {
prices: {},
discountPercent: 0,
};
const actions = {
setPrice( item, price ) {
return {
type: 'SET_PRICE',
item,
price,
};
},
startSale( discountPercent ) {
return {
type: 'START_SALE',
discountPercent,
};
},
fetchFromAPI( path ) {
return {
type: 'FETCH_FROM_API',
path,
};
},
};
const store = createReduxStore( 'my-shop', {
reducer( state = DEFAULT_STATE, action ) {
switch ( action.type ) {
case 'SET_PRICE':
return {
...state,
prices: {
...state.prices,
[ action.item ]: action.price,
},
};
case 'START_SALE':
return {
...state,
discountPercent: action.discountPercent,
};
}
return state;
},
actions,
selectors: {
getPrice( state, item ) {
const { prices, discountPercent } = state;
const price = prices[ item ];
return price * ( 1 - 0.01 * discountPercent );
},
},
controls: {
FETCH_FROM_API( action ) {
return apiFetch( { path: action.path } );
},
},
resolvers: {
*getPrice( item ) {
const path = '/wp/v2/prices/' + item;
const price = yield actions.fetchFromAPI( path );
return actions.setPrice( item, price );
},
},
} );
register( store );
- `````name````` (`````string`````) – ストアの名前
- `````instantiate````` (`````Function`````) – 次のメソッドを持つ[Reduxライクなストアオブジェクト](https://redux.js.org/basics/store)を返します:
- `````getState()`````: 登録されたリデューサーの状態値を返します
- Reduxの並行: [`````getState`````](https://redux.js.org/api/store#getstate)
- `````subscribe( listener: Function )`````: 状態の値が変更されるたびに呼び出される関数を登録します。
- Reduxの並行: [`````subscribe`````](https://redux.js.org/api/store#subscribelistener)
- `````dispatch( action: Object )`````: アクションオブジェクトを与えられた場合、登録されたリデューサーを呼び出し、状態値を更新します。
- Reduxの並行: [`````dispatch`````](https://redux.js.org/api/store#dispatchaction)
<a name="redux-store-options"></a>
### Reduxストアオプション
#### リデューサー
[**リデューサー**](https://redux.js.org/basics/reducers)は、前の`````state`````と`````action`````を引数として受け取り、更新された`````state`````値を返す関数です。
#### アクション
**`````actions`````**オブジェクトは、ストアで利用可能なすべての[action creators](https://redux.js.org/glossary#action-creator)を説明する必要があります。アクションクリエイターは、オプションで引数を受け取り、登録されたリデューサーにディスパッチするアクションオブジェクトを返す関数です。*アクションをディスパッチすることは、状態を変更するための主要なメカニズムです。*
#### セレクター
**`````selectors`````**オブジェクトには、状態値にアクセスし、導出するための関数のセットが含まれています。セレクターは、状態とオプションの引数を受け取り、状態からいくつかの値を返す関数です。*セレクターを呼び出すことは、状態からデータを取得するための主要なメカニズムです*、そして通常は変更に対してより敏感で、[正規化されたオブジェクト](https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#designing-a-normalized-state)としてはあまり使いやすくない生データの上に有用な抽象化を提供します。
#### リゾルバー
**リゾルバー**は、セレクターの副作用です。セレクターの結果が外部ソースから満たされる必要がある場合、最初にセレクターが呼び出されたときに満たす動作が行われるようにリゾルバーを定義できます。
`````resolvers`````オプションは、各キーが作用するセレクターの名前であり、値がセレクターに渡されるのと同じ引数を受け取る関数であるオブジェクトとして渡す必要があります。これにより、必要に応じてセレクターの要件を満たすためにディスパッチできます。ほとんどのデータ消費者がその後の状態変更にサブスクライブすることを考慮に入れています(`````subscribe`````または`````withSelect`````)。
#### コントロール
**コントロール**は、特定のアクションタイプに関連付けられた実行フローベヘイビアを定義します。これは、ストアの非同期データフローを実装する際に特に便利です。特定の制御されたアクションタイプを生成するジェネレーターとしてアクションクリエイターやリゾルバーを定義することにより、実行はコントロールハンドラーによって定義された通りに進行します。
`````controls`````オプションは、各キーが作用するアクションタイプの名前であり、値が元のアクションオブジェクトを受け取る関数であるオブジェクトとして渡す必要があります。これは、評価が続行されるべき時に解決される約束を返すか、値を返す必要があります。値または解決された約束の値は、yield割り当ての戻り値に割り当てられます。コントロールハンドラーがundefinedを返す場合、実行は続行されません。
詳細については、[`````@wordpress/redux-routine`````のドキュメント](https://github.com/WordPress/gutenberg/tree/HEAD/packages/redux-routine/README.md)を参照してください。
#### 初期状態
ストアのためのオプションのプリロードされた初期状態です。これを使用して、いくつかのシリアライズされた状態値やサーバーサイドで生成された状態を復元できます。
<a name="generic-stores"></a>
## 一般的なストア
`````@wordpress/data`````モジュールは、他のデータシステムとの統合や、データシステムに対するより直接的な制御が必要な状況のために、より高度で一般的なインターフェースを提供します。この場合、データストアは`````@wordpress/data`````の外部で実装され、その後3つの関数を介して接続される必要があります:
- `````getSelectors()`````: ストアに事前にマッピングされたセレクター関数のオブジェクトを返します。
- `````getActions()`````: ストアに事前にマッピングされたアクション関数のオブジェクトを返します。
- `````subscribe( listener: Function )`````: 状態の値が変更されるたびに呼び出される関数を登録します。
- 次の違いを持つRedux[`````subscribe`````](https://redux.js.org/api/store#subscribelistener)として動作します:
- アンソ subscribeを実装する必要はありません。レジストリはそれを使用しないためです。
- 1つのリスナー(レジストリ)のみをサポートする必要があります。
カスタムストアのために上記のインターフェースを実装することにより、レジストリと`````withSelect`````および`````withDispatch`````の高階コンポーネントをアプリケーションコードで使用する利点を得ることができます。これにより、既存のデータシステムや代替データシステムとのシームレスな統合が提供されます。
既存のreduxストアを独自のリデューサー、ストアエンハンサー、ミドルウェアと統合することは、次のように実行できます:
*例:*
``````bash
import { register } from '@wordpress/data';
import existingSelectors from './existing-app/selectors';
import existingActions from './existing-app/actions';
import createStore from './existing-app/store';
const reduxStore = createStore();
const mapValues = ( obj, callback ) =>
Object.entries( obj ).reduce(
( acc, [ key, value ] ) => ( {
...acc,
[ key ]: callback( value ),
} ),
{}
);
const boundSelectors = mapValues(
existingSelectors,
( selector ) =>
( ...args ) =>
selector( reduxStore.getState(), ...args )
);
const boundActions = mapValues(
existingActions,
( action ) =>
( ...args ) =>
reduxStore.dispatch( action( ...args ) )
);
const genericStore = {
name: 'existing-app',
instantiate: () => ( {
getSelectors: () => boundSelectors,
getActions: () => boundActions,
subscribe: reduxStore.subscribe,
} ),
};
register( genericStore );
`
完全にカスタムストアをゼロから実装することも可能です:
例:
import { register } from '@wordpress/data';
function customStore() {
return {
name: 'custom-data',
instantiate: () => {
const listeners = new Set();
const prices = { hammer: 7.5 };
function storeChanged() {
for ( const listener of listeners ) {
listener();
}
}
function subscribe( listener ) {
listeners.add( listener );
return () => listeners.delete( listener );
}
const selectors = {
getPrice( itemName ) {
return prices[ itemName ];
},
};
const actions = {
setPrice( itemName, price ) {
prices[ itemName ] = price;
storeChanged();
},
};
return {
getSelectors: () => selectors,
getActions: () => actions,
subscribe,
};
},
};
}
register( customStore );
Reduxとの比較
データモジュールは、Reduxのコア原則やAPIメソッド名の多くを共有しています。実際、Reduxの上に実装されています。異なる点は、別々だが相互依存するストアを作成するためのモジュール化パターンを確立し、データアクセスの主要なエントリポイントとしてセレクター関数などの慣習を体系化することです。
この区別を補完するために高階コンポーネントが作成されました。withSelect
とwithDispatch
を分割する意図は、React Reduxではconnect
の下でmapStateToProps
およびmapDispatchToProps
引数として結合されているため、ディスパッチが状態変更へのサブスクリプションに依存しないことをより正確に反映し、状態から派生した値をwithDispatch
で使用できるようにすることです(高階コンポーネントの合成を介して)。
データモジュールには、リゾルバーやコントロールを通じて非同期副作用を処理するための組み込みソリューションもあります。これらは、https://redux.js.org/advanced/async-actionsのような標準redux非同期ソリューションとは若干異なります。
ReduxおよびReact Reduxとの具体的な実装の違い:
- Reduxでは、
subscribe
リスナーは、状態の値が変更されたかどうかに関係なく、すべてのディスパッチで呼び出されます。@wordpress/data
では、サブスクライバーは状態が変更されたときのみ呼び出されます。
- React Reduxでは、
mapStateToProps
関数はオブジェクトを返す必要があります。@wordpress/data
では、withSelect
マッピング関数は、注入するプロパティがない場合、undefined
を返すことができます。
- React Reduxでは、
mapDispatchToProps
引数はオブジェクトまたは関数として定義できます。
API
AsyncModeProvider
データモジュールコンポーネントの再レンダリングを同期モードと非同期モードの間で切り替えるために使用されるコンテキストプロバイダーコンポーネント。
使用法
import { useSelect, AsyncModeProvider } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';
function BlockCount() {
const count = useSelect( ( select ) => {
return select( blockEditorStore ).getBlockCount();
}, [] );
return count;
}
function App() {
return (
<AsyncModeProvider value={ true }>
<BlockCount />
</AsyncModeProvider>
);
}
この例では、BlockCountコンポーネントが非同期に再レンダリングされます。
つまり、より重要なタスクが実行されている場合(入力にタイプするなど)、
再レンダリングはブラウザがアイドルになるまで遅延されます。
複数のレベルのAsyncModeProviderをネストして、レンダリング動作を微調整することが可能です。
パラメータ
- props.value
boolean
: 非同期モードを有効にします。
戻り値
combineReducers
combineReducersヘルパー関数は、値が異なるリデューシング関数のオブジェクトを、registerReducerに渡すことができる単一のリデューシング関数に変換します。
使用法
import { combineReducers, createReduxStore, register } from '@wordpress/data';
const prices = ( state = {}, action ) => {
return action.type === 'SET_PRICE'
? {
...state,
[ action.item ]: action.price,
}
: state;
};
const discountPercent = ( state = 0, action ) => {
return action.type === 'START_SALE' ? action.discountPercent : state;
};
const store = createReduxStore( 'my-shop', {
reducer: combineReducers( {
prices,
discountPercent,
} ),
} );
register( store );
タイプ
import('./types').combineReducers
パラメータ
- reducers
Object
: 結合する必要がある異なるリデューシング関数に対応する値を持つオブジェクトです。
戻り値
コントロール
createReduxStore
リデューサー、アクション、セレクター、コントロール、リゾルバーを説明するプロパティを含む、提供されたReduxストア構成のためのデータストア記述子を作成します。
使用法
import { createReduxStore } from '@wordpress/data';
const store = createReduxStore( 'demo', {
reducer: ( state = 'OK' ) => state,
selectors: {
getValue: ( state ) => state,
},
} );
パラメータ
- key
string
: ユニークな名前空間識別子。 - options
ReduxStoreConfig<State,Actions,Selectors>
: リデューサー、アクション、セレクター、リゾルバーを説明するプロパティを持つ登録されたストアオプションです。
戻り値
createRegistry
オプションの初期ストア構成オブジェクトを与えられた新しいストアレジストリを作成します。
パラメータ
- storeConfigs
Object
: 初期ストア構成。 - parent
Object?
: 親レジストリ。
戻り値
createRegistryControl
追加のカリー引数をregistry
オブジェクトで受け取るコントロール関数を作成します。通常のコントロールは署名を持ちます
( action ) => iteratorOrPromise;
コントロールがバインドされているaction
で動作するのに対し、レジストリコントロールは署名を持ちます:
( registry ) => ( action ) => iteratorOrPromise;
レジストリコントロールは通常、データを選択したり、登録されたストアにアクションをディスパッチするために使用されます。
*パラメータ*
- registryControl `````Function`````: レジストリオブジェクトを受け取り、コントロールを返す関数です。
*戻り値*
- `````Function`````: ストアに登録できるレジストリコントロールです。
<a name="createregistryselector"></a>
### createRegistrySelector
レジストリ`````select`````関数で追加のカリー引数を受け取るセレクター関数を作成します。通常のセレクターは署名を持ちます
``````bash
( state, ...selectorArgs ) => result;
`
ストアのstate
からデータを選択することを可能にしますが、レジストリセレクターは署名を持ちます:
( select ) =>
( state, ...selectorArgs ) =>
result;
他の登録されたストアからも選択をサポートします。
使用法
import { store as coreStore } from '@wordpress/core-data';
import { store as editorStore } from '@wordpress/editor';
const getCurrentPostId = createRegistrySelector( ( select ) => ( state ) => {
return select( editorStore ).getCurrentPostId();
} );
const getPostEdits = createRegistrySelector( ( select ) => ( state ) => {
// calling another registry selector just like any other function
const postType = getCurrentPostType( state );
const postId = getCurrentPostId( state );
return select( coreStore ).getEntityRecordEdits(
'postType',
postType,
postId
);
} );
(通常の非レジストリセレクター内でも機能します)そして、
レジストリを引数として渡す必要はありません。セレクターをストアに登録するときにレジストリバインディングが自動的に行われます。
*パラメータ*
- registrySelector `````Function`````: レジストリ`````select`````関数を受け取り、状態セレクターを返す関数です。
*戻り値*
- `````Function`````: ストアに登録できるレジストリセレクターです。
<a name="createselector"></a>
### createSelector
依存関係の配列とセレクターのパラメータに従って計算された値をキャッシュするメモ化されたセレクターを作成し、いずれかが変更されたときのみ値を再計算します。
*関連*
- `````rememo`````パッケージのドキュメント、`````createSelector`````関数が再エクスポートされています。
*パラメータ*
- selector `````Function`````: 状態とパラメータから値を計算するセレクター関数です。
- getDependants `````Function`````: “依存”オブジェクトの配列を返す関数です。
*戻り値*
- `````Function`````: 計算された戻り値をキャッシュする`````selector`````のメモ化バージョンです。
<a name="dispatch"></a>
### dispatch
ストア記述子が与えられた場合、ストアのアクションクリエイターのオブジェクトを返します。アクションクリエイターを呼び出すと、それがディスパッチされ、状態値がそれに応じて更新されます。
注意:ディスパッチによって返されたアクションクリエイターは、呼び出されると約束を返します。
*使用法*
``````bash
import { dispatch } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
dispatch( myCustomStore ).setPrice( 'hammer', 9.75 );
`
パラメータ
- storeNameOrDescriptor
StoreNameOrDescriptor
: ストア記述子。ストア名を渡すレガシー呼び出し規約もサポートされています。
戻り値
プラグイン
レジストリで使用できるプラグインのオブジェクトです。
関連
タイプ
register
標準の@wordpress/data
ストア記述子を登録します。
使用法
import { createReduxStore, register } from '@wordpress/data';
const store = createReduxStore( 'demo', {
reducer: ( state = 'OK' ) => state,
selectors: {
getValue: ( state ) => state,
},
} );
register( store );
パラメータ
registerGenericStore
非推奨
register( storeDescriptor )
を使用してください。
一般的なストアインスタンスを登録します。
パラメータ
registerStore
非推奨
register
を使用してください。
標準の@wordpress/data
ストアを登録します。
パラメータ
- storeName
string
: ストアのユニークな名前空間識別子。 - options
Object
: ストアの説明(リデューサー、アクション、セレクター、リゾルバー)。
戻り値
RegistryConsumer
提供されたregistry
を子コンポーネントに公開するカスタムReactコンテキストコンシューマです。RegistryProviderと一緒に使用されます。
ReactコンテキストAPIについての詳細は、こちらを参照してください:https://react.dev/learn/passing-data-deeply-with-context#step-3-provide-the-context
使用法
import {
RegistryProvider,
RegistryConsumer,
createRegistry
} from '@wordpress/data';
const registry = createRegistry( {} );
const App = ( { props } ) => {
return <RegistryProvider value={ registry }>
<div>Hello There</div>
<RegistryConsumer>
{ ( registry ) => (
<ComponentUsingRegistry
{ ...props }
registry={ registry }
) }
</RegistryConsumer>
</RegistryProvider>
}
RegistryProvider
提供されたregistry
を子コンポーネントに公開するカスタムコンテキストプロバイダーです。
例については、
RegistryConsumerのドキュメントを参照してください。
resolveSelect
ストア記述子が与えられた場合、ストアのセレクターを状態に事前にバインドしたオブジェクトを返します。これにより、追加の引数を供給するだけで済み、リゾルバーが実行された後に最終的な値に解決される約束を返すように修正されます。
使用法
import { resolveSelect } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
resolveSelect( myCustomStore ).getPrice( 'hammer' ).then( console.log );
パラメータ
- storeNameOrDescriptor
StoreDescriptor|string
: ストア記述子。ストア名を渡すレガシー呼び出し規約もサポートされています。
戻り値
select
ストア記述子が与えられた場合、ストアのセレクターのオブジェクトを返します。セレクター関数は、現在の状態を自動的に渡すように事前にバインドされています。消費者として、適用可能な場合はセレクターの引数のみを渡す必要があります。
使用法
import { select } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
select( myCustomStore ).getPrice( 'hammer' );
パラメータ
- storeNameOrDescriptor
string | T
: ストア記述子。ストア名を渡すレガシー呼び出し規約もサポートされています。
戻り値
subscribe
リスナー関数が与えられた場合、登録されたストアの1つの状態値が変更されるたびにその関数が呼び出されます。オプションのstoreNameOrDescriptor
パラメータを指定すると、リスナー関数はその特定の登録ストアの更新時にのみ呼び出されます。
この関数は、サブスクリプションを停止するために使用されるunsubscribe
関数を返します。
使用法
import { subscribe } from '@wordpress/data';
const unsubscribe = subscribe( () => {
// You could use this opportunity to test whether the derived result of a
// selector has subsequently changed as the result of a state update.
} );
// Later, if necessary...
unsubscribe();
パラメータ
suspendSelect
ストア記述子が与えられた場合、ストアのセレクターを状態に事前にバインドしたオブジェクトを返します。これにより、追加の引数を供給するだけで済み、セレクターがまだ解決されていない場合に約束をスローするように修正されます。
パラメータ
- storeNameOrDescriptor
StoreDescriptor|string
: ストア記述子。ストア名を渡すレガシー呼び出し規約もサポートされています。
戻り値
use
レジストリを拡張して、指定されたプラグインによって提供される機能を継承します。プラグインは、レジストリのプロパティに一致するプロパティを持つオブジェクトで、デフォルトのレジストリ動作を拡張するためにマージされます。
パラメータ
useDispatch
現在のレジストリディスパッチアクションクリエイターを返すカスタムReactフックです。
注意:このフックを使用するコンポーネントは、RegistryProviderのコンテキスト内に存在する必要があります。
使用法
これは、サーバーから動的データを取得する必要があるパターンを示しています
``````bash
import { useCallback } from 'react';
import { useDispatch, useSelect } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
function Button( { onClick, children } ) {
return (
<button type="button" onClick={ onClick }>
{ children }
</button>
);
}
const SaleButton = ( { children } ) => {
const { stockNumber } = useSelect(
( select ) => select( myCustomStore ).getStockNumber(),
[]
);
const { startSale } = useDispatch( myCustomStore );
const onClick = useCallback( () => {
const discountPercent = stockNumber > 50 ? 10 : 20;
startSale( discountPercent );
}, [ stockNumber ] );
return <Button onClick={ onClick }>{ children }</Button>;
};
// Rendered somewhere in the application:
//
// <SaleButton>Start Sale!</SaleButton>
`
パラメータ
- storeNameOrDescriptor
[StoreNameOrDescriptor]
: アクションクリエイターを取得するためのストア名またはその記述子をオプションで提供します。提供されない場合、registry.dispatch関数が代わりに返されます。
戻り値
useRegistry
レジストリコンテキストを使用するために公開するカスタムReactフックです。
これは、Registry Providerを介して提供されたregistry
値を、このフックを実装するコンポーネントに公開します。
useContext
Reactフックと同様に動作します。
注意:一般的に、useRegistry
は実装に必要ない低レベルのフックです。@wordpress/data
APIとのほとんどの相互作用は、useSelect
フック、またはwithSelect
およびwithDispatch
の高階コンポーネントを介して実行できます。
使用法
import { RegistryProvider, createRegistry, useRegistry } from '@wordpress/data';
const registry = createRegistry( {} );
const SomeChildUsingRegistry = ( props ) => {
const registry = useRegistry();
// ...logic implementing the registry in other react hooks.
};
const ParentProvidingRegistry = ( props ) => {
return (
<RegistryProvider value={ registry }>
<SomeChildUsingRegistry { ...props } />
</RegistryProvider>
);
};
戻り値
useSelect
登録されたセレクターからプロパティを取得するためのカスタムReactフックです。
一般的に、このカスタムReactフックはフックのルールに従います。
使用法
import { useSelect } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
function HammerPriceDisplay( { currency } ) {
const price = useSelect(
( select ) => {
return select( myCustomStore ).getPrice( 'hammer', currency );
},
[ currency ]
);
return new Intl.NumberFormat( 'en-US', {
style: 'currency',
currency,
} ).format( price );
}
// Rendered in the application:
// <HammerPriceDisplay currency="USD" />
上記の例では、HammerPriceDisplay
がアプリケーションにレンダリングされると、価格はmapSelect
コールバックを使用してストア状態から取得されます。通貨プロパティが変更されると、
その通貨の状態内の価格が取得されます。通貨プロパティが変更されず、他のプロパティが変更される場合、依存関係が通貨だけであるため、価格は変更されません。
データがイベントコールバック内でのみ使用される場合、データはレンダリング時に取得されるべきではないため、セレクター関数を取得する方が便利です。
レンダリング時にセレクターを呼び出す際にuseSelect
をこのように使用しないでください
データ変更時にコンポーネントが再レンダリングされないためです。
import { useSelect } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
function Paste( { children } ) {
const { getSettings } = useSelect( myCustomStore );
function onPaste() {
// Do something with the settings.
const settings = getSettings();
}
return <div onPaste={ onPaste }>{ children }</div>;
}
パラメータ
- mapSelect
T
: 状態変更ごとに呼び出される関数。返された値は、このフックを実装するコンポーネントに公開されます。関数は、最初の引数にregistry.select
メソッドを、2番目の引数にregistry
を受け取ります。ストアキーが渡されると、ストアのすべてのセレクターが返されます。これは、要素ツリーを作成するために必要なデータではなく、イベントコールバック内でこれらのセレクターを使用するためのものです。 - deps
unknown[]
: 提供される場合、これはmapSelectをメモ化し、依存関係が変更されない限り、同じmapSelect
が状態変更ごとに呼び出されます。
戻り値
useSuspenseSelect
*パラメータ*
- mapSelect `````T`````: 状態変更ごとに呼び出される関数。返された値は、このフックを使用するコンポーネントに公開されます。関数は、最初の引数に`````registry.suspendSelect`````メソッドを、2番目の引数に`````registry`````を受け取ります。
- deps `````Array`````: 依存関係配列で、`````mapSelect`````をメモ化するために使用され、依存関係が変更されない限り、同じ`````mapSelect`````が状態変更ごとに呼び出されます。
*戻り値*
- `````ReturnType<T>`````: `````mapSelect`````関数によって返されるデータオブジェクトです。
<a name="withdispatch"></a>
### withDispatch
登録されたアクションクリエイターを使用してディスパッチプロパティを追加するために使用される高階コンポーネントです。
*使用法*
``````bash
function Button( { onClick, children } ) {
return (
<button type="button" onClick={ onClick }>
{ children }
</button>
);
}
import { withDispatch } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
const SaleButton = withDispatch( ( dispatch, ownProps ) => {
const { startSale } = dispatch( myCustomStore );
const { discountPercent } = ownProps;
return {
onClick() {
startSale( discountPercent );
},
};
} )( Button );
// Rendered in the application:
//
// <SaleButton discountPercent="20">Start Sale!</SaleButton>
`
ほとんどのケースでは、mapDispatchToProps
に渡される最初の2つのパラメータを使用するだけで十分です。
ただし、registry
オブジェクトを使用してコンポーネントのパフォーマンスを最適化するための非常に高度な使用例があるかもしれません。select
関数をレジストリから使用することは、イベントが発生したときにストアから動的データを取得する必要がある場合に便利ですが、同時にそれを使用してコンポーネントをレンダリングすることはありません。このようなシナリオでは、withSelect
高階コンポーネントを使用してそのプロパティを計算することを避けることができ、頻繁な値の変更によって引き起こされる不必要な再レンダリングを回避できます。
``````bash
function Button( { onClick, children } ) {
return (
<button type="button" onClick={ onClick }>
{ children }
</button>
);
}
import { withDispatch } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
const SaleButton = withDispatch( ( dispatch, ownProps, { select } ) => {
// Stock number changes frequently.
const { getStockNumber } = select( myCustomStore );
const { startSale } = dispatch( myCustomStore );
return {
onClick() {
const discountPercent = getStockNumber() > 50 ? 10 : 20;
startSale( discountPercent );
},
};
} )( Button );
// Rendered in the application:
//
// <SaleButton>Start Sale!</SaleButton>
`
注意: mapDispatchToProps
関数が常に同じキーを持つオブジェクトを返すことが重要です。たとえば、異なる値が返される条件を含めるべきではありません。
パラメータ
- mapDispatchToProps
Function
: プロパティ名のオブジェクトを返す関数で、値はディスパッチバウンドアクションクリエイターであるか、コンポーネントのプロパティを使用して呼び出され、アクションクリエイターを返す関数です。
戻り値
withRegistry
現在のレジストリコンテキストをregistry
プロパティとして渡して元のコンポーネントをレンダリングする高階コンポーネントです。
パラメータ
- OriginalComponent
Component
: 元のコンポーネントです。
戻り値
withSelect
登録されたセレクターを使用して状態派生プロパティを注入するために使用される高階コンポーネントです。
使用法
import { withSelect } from '@wordpress/data';
import { store as myCustomStore } from 'my-custom-store';
function PriceDisplay( { price, currency } ) {
return new Intl.NumberFormat( 'en-US', {
style: 'currency',
currency,
} ).format( price );
}
const HammerPriceDisplay = withSelect( ( select, ownProps ) => {
const { getPrice } = select( myCustomStore );
const { currency } = ownProps;
return {
price: getPrice( 'hammer', currency ),
};
} )( PriceDisplay );
// Rendered in the application:
//
// <HammerPriceDisplay currency="USD" />
上記の例では、HammerPriceDisplay
がアプリケーションにレンダリングされると、価格は基盤となるPriceDisplay
コンポーネントに渡され、ハンマーの価格がストアで変更されると自動的に更新されます。
パラメータ
- mapSelectToProps
Function
: 状態変更ごとに呼び出される関数で、コンポーネントのプロパティとマージするプロパティのオブジェクトを返すことが期待されます。
戻り値
batch
- セレクターは更新された状態で呼び出されます。
- セレクターが前の値(厳密な等価性)と異なる値を返す場合、コンポーネントは再レンダリングされます。
アプリケーションが成長するにつれて、これはコストがかかる可能性があるため、可能な限りこれらの両方を実行しないようにすることが重要です。これらの状況の1つは、相互作用が状態を適切に更新するために複数の連続した`````dispatch`````呼び出しを必要とする場合に発生します。`````dispatch`````を呼び出すたびにコンポーネントを再レンダリングしないようにするために、連続したディスパッチ呼び出しを`````batch`````でラップすることができ、これによりコンポーネントは選択子を呼び出し、シーケンスの最後に1回だけ再レンダリングされます。
*使用法*
``````bash
import { useRegistry } from '@wordpress/data';
function Component() {
const registry = useRegistry();
function callback() {
// This will only rerender the components once.
registry.batch( () => {
registry.dispatch( someStore ).someAction();
registry.dispatch( someStore ).someOtherAction();
} );
}
return <button onClick={ callback }>Click me</button>;
}
`
セレクター
wp.data.select( 'core' )
によって返されるオブジェクトで利用可能な次のセレクターです。
例
import { store as coreDataStore } from '@wordpress/core-data';
import { useSelect } from '@wordpress/data';
function Component() {
const result = useSelect( ( select ) => {
const query = { per_page: 20 };
const selectorArgs = [ 'postType', 'page', query ];
return {
pages: select( coreDataStore ).getEntityRecords( ...selectorArgs ),
hasStartedResolution: select( coreDataStore ).hasStartedResolution(
'getEntityRecords', // _selectorName_
selectorArgs
),
hasFinishedResolution: select(
coreDataStore
).hasFinishedResolution( 'getEntityRecords', selectorArgs ),
isResolving: select( coreDataStore ).isResolving(
'getEntityRecords',
selectorArgs
),
};
} );
if ( result.hasStartedResolution ) {
return <>Fetching data...</>;
}
if ( result.isResolving ) {
return (
<>
{
// show a spinner
}
</>
);
}
if ( result.hasFinishedResolution ) {
return (
<>
{
// data is ready
}
</>
);
}
}
hasFinishedResolution
指定されたセレクター名と引数セットの解決が完了した場合はtrueを返します。
パラメータ
- state
State
: データ状態です。 - selectorName
string
: セレクター名です。 - args
unknown[]?
: セレクターに渡される引数です。
戻り値
hasStartedResolution
指定されたセレクター名と引数セットの解決がすでにトリガーされている場合はtrueを返します。
パラメータ
- state
State
: データ状態です。 - selectorName
string
: セレクター名です。 - args
unknown[]?
: セレクターに渡される引数です。
戻り値
isResolving
指定されたセレクター名と引数セットの解決がトリガーされているが、まだ完了していない場合はtrueを返します。
パラメータ
- state
State
: データ状態です。 - selectorName
string
: セレクター名です。 - args
unknown[]?
: セレクターに渡される引数です。
戻り値
セレクタ引数の正規化
特定の状況では、セレクタ/リゾルバのペアリングの特定の 呼び出し に渡される引数を正規化する必要がある場合があります。
各リゾルバは、内部状態にキャッシュされた解決ステータスを持ち、キーは 呼び出し 時にセレクタに供給された引数です。
例えば、単一の引数を持つセレクタの場合、関連するリゾルバは次のキャッシュキーを生成します: [ 123 ]
。
このキャッシュは、特定のリゾルバの解決ステータスを決定するために使用されます これは、不要な追加のリゾルバの呼び出しを避けるために使用されます(これらはしばしばネットワークリクエストなどの「高コスト」な操作を行います)。
その結果、セレクタを呼び出す際に引数が 一貫性 を保つことが重要です。例えば、デフォルト では、これらの2つの呼び出しは同じキーを使用してキャッシュされませんが、実際には同一である可能性があります:
// Arg as number
getSomeDataById( 123 );
// Arg as string
getSomeDataById( '123' );
これは、unstableNormalizeArgs
プロパティを利用して、一貫性を保証し、呼び出し元が不正な型を渡すことから保護する機会です。
例
以下のセレクタの 3番目 の引数は Number
であることを意図しています:
const getItemsSelector = ( name, type, id ) => {
return state.items[ name ][ type ][ id ] || null;
};
しかし、id
パラメータが String
として渡される可能性があります。この場合、unstableNormalizeArgs
メソッド(プロパティ)を セレクタ に定義して、引数を望ましい型に強制することができます。たとえそれらが「不正に」提供されても:
// Define normalization method.
getItemsSelector.__unstableNormalizeArgs = ( args ) {
// "id" argument at the 2nd index
if (args[2] && typeof args[2] === 'string' ) {
args[2] === Number(args[2]);
}
return args;
}
これが整っていれば、次のコードは一貫して動作します:
const getItemsSelector = ( name, type, id ) => {
// here 'id' is now guaranteed to be a number.
return state.items[ name ][ type ][ id ] || null;
};
const getItemsResolver = ( name, type, id ) => {
// 'id' is also guaranteed to be a number in the resolver.
return {};
};
registry.registerStore( 'store', {
// ...
selectors: {
getItems: getItemsSelector,
},
resolvers: {
getItems: getItemsResolver,
},
} );
// Call with correct number type.
registry.select( 'store' ).getItems( 'foo', 'bar', 54 );
// Call with the wrong string type, **but** here we have avoided an
// wanted resolver call because '54' is guaranteed to have been
// coerced to a number by the `__unstableNormalizeArgs` method.
registry.select( 'store' ).getItems( 'foo', 'bar', '54' );
特定のセレクタ呼び出しの引数の一貫性を確保することは、データ層のパフォーマンスを向上させるための重要な最適化です。しかし、この種の問題は、通常、セレクタが引数に可変型を使用しないようにすることで回避できます。
さらに進む
このパッケージへの貢献
これはグーテンベルクプロジェクトの一部である個別のパッケージです。このプロジェクトはモノレポとして整理されています。特定の目的を持つ複数の自己完結型ソフトウェアパッケージで構成されています。このモノレポ内のパッケージはnpmに公開され、WordPressや他のソフトウェアプロジェクトで使用されています。
このパッケージやグーテンベルク全体への貢献について詳しく知りたい場合は、プロジェクトの主な貢献者ガイドをお読みください。