親愛なる同僚の皆さん、React xstoreアプリケーションの状態を管理するためのコンテナーに注意を向けて非難します。 大きくてキラキラ輝くReduxバイクの隣にあるのは、間違いなくこのような小さな子供用バイクです。 私たちJavaScriptプログラマーは皆、とても大きくてペースの遅い自転車製造工場です。
多かれ少なかれ初心者でも初心者でも、React JavaScript Reduxプログラマーとの知り合いは少し複雑に見えるかもしれません。
よく見てみましょう。
設置
npm install --save xstore
使用する
最初に、リポジトリに「ハンドラ」を追加する必要があります。
(ハンドラーの例を下のブロックに示します)
index.js
import React from 'react' import ReactDOM from 'react-dom' import Store from 'xstore' import App from './components/App' import user from './store_handlers/user' import dictionary from './store_handlers/dictionary' // "_". // : user dictionary. Store.addHandlers({ user, dictionary }); ReactDOM.render( <App/>, document.getElementById('root') );
以下は、「ユーザー」ハンドラーの例です。
ユーザーリポジトリの初期状態を判断するために必要なリデューサーの初期化が含まれています。
./store_handlers/user.js
import axios from 'axios' const DEFAULT_STATE = { name: 'user', status: 'alive' } /** =============== Reducers =============== */ // . // , . // , . // this.props.dispatch('USER_INIT'). const init = () => { return DEFAULT_STATE; } // this.props.dispatch('USER_CHANGED', {name: 'NewName'}) const changed = (state, data) => { return { ...state, ...data } } /** =============== Actions =============== */ // this.props.doAction('USER_CHANGE', {data}) const change = ({dispatch}, data) => { // {dispatch, doAction, getState, state} dispatch('USER_CHANGED', data); } // this.props.doAction('USER_LOAD', {id: userId}) const load = ({dispatch}, data) => { // {dispatch, doAction, getState, state} axios.get('/api/load.php', data) .then(({data}) => { dispatch('USER_CHANGED', data); }); } // export default { actions: { load, change // remove, save, add_item, remove_this_extra_item, ..... }, reducers: { init, changed // removed, saved, item_added, this_extra_item_removed, ..... } }
以下は、コンポーネントをリポジトリに接続する方法の例です。
./components/ComponentToConnect/index.js
import React from 'react' import Store from 'xstore' class ComponentToConnect extends React.Component { render() { // user dictionary . let {user, dictionary} = this.props; return ( <div className="some-component"> .... </div> ) } loadUser(userId) { // . this.props.doAction('USER_LOAD', {id: userId}); } setUser(userData) { // . // . this.props.dispatch('USER_CHANGED', userData); } } // . const params = { has: 'user, dictionary' } export default Store.connect(ComponentToConnect, params);
接続に使用可能なparamsオプション:
{ // , : has: 'user, dictionary', // -: has: ['user', 'dictionary'], // : has: 'user:name|status, dictionary:userStatuses', // has: ['user:name|status', 'dictionary:userStatuses'], // , . shouldHave: 'user,dictionary', // shouldHave: ['user', 'dictionary'], // , true. // "name", "status", "userStatuses" "user" "dictionary" flat: true, // , , flat = true. // "user_name", "user_status", "dictionary_userStatuses" withPrefix: true, // . // , "has" . handlers: { user, dictionary } }
パブリックリポジトリメソッドのリスト:
import Store from 'xstore' // : let state = Store.getState(); // "user": let userState = Store.getState('user'); // "name" "user": let userName = Store.getState('user.name'); // 0 "items" "user": let someItem = Store.getState('user.items.0'); // : Store.addHandlers({ user: userHandler, dictionary: dictionaryHandler }) // "load" "user": // , . Store.doAction('USER_LOAD', {id: userId}); // "loaded" "user": Store.dispatch('USER_LOADED', data); // : Store.connect(Component, params);
そして、それがどのように機能するかについて:
「connect」メソッドは、新しいHOCクラスXStoreConnectを作成します。これは、コンポーネントとストレージの相互作用のすべてのロジックを隠します。 このクラスはストレージの変更にサブスクライブし、そこで何らかの変更が発生すると、外部呼び出しから保護されたsetStateメソッドを呼び出し(たとえば、this.refs.xStoreConnect.setState(...)を介して)、その後、このコンポーネントが再描画され、それによって更新されますラップされたコンポーネントの小道具。
ラッパーコンポーネントの状態を直接変更するthis.refs.xStoreConnect.state =何も何も起こらない場合、このクラスは埋め込みデータを見つけて削除できます。
// .... const LOCAL_OBJECT_CHECKER = {}; const connect = (ComponentToConnect, connectProps) => { let ready = false; let { has, handlers, shouldHave: shouldHaveString, flat, withPrefix } = connectProps; if (!has && handlers instanceof Object) { has = Object.keys(handlers); } let shouldHave = []; if (typeof shouldHaveString == 'string') { shouldHaveString = shouldHaveString.split(','); for (let item of shouldHaveString) { if (item) { shouldHave.push(item.trim()); } } } let doUnsubscribe, doCleanState, stateItemsQuantity; return class XStoreConnect extends React.Component { constructor() { super(); const updater = (state) => { stateItemsQuantity = Object.keys(state).length; if (ready) { this.setState(state, LOCAL_OBJECT_CHECKER); } else { this.state = state; } } doUnsubscribe = () => { unsubscribe(updater); } doCleanState = () => { cleanStateFromInjectedItems(updater, this.state); } subscribe(updater, {has, handlers, flat, withPrefix}); } setState(state, localObjectChecker) { if (state instanceof Object && localObjectChecker === LOCAL_OBJECT_CHECKER) { super.setState(state); } } componentWillMount() { ready = true; } componentWillUnmount() { ready = false; doUnsubscribe(); } render() { let {props, state} = this; let newStateKeysQuantity = Object.keys(state).length; if (stateItemsQuantity != newStateKeysQuantity) { doCleanState(); } for (let item of shouldHave) { if (state[item] === undefined) { return null; } } let componentProps = { ...props, ...state, doAction, dispatch }; return <ComponentToConnect {...componentProps}/> } } }
コマンドラインからハンドラーファイルを生成する:
npm install -g xstore xstore create-handler filename
「package.json」の「scripts」で記述することもできます。
{ scripts: { "create-handler": "node node_modules/xstore/bin/exec.js" } } npm run create-handler filename
このコマンドは、ハンドラーのテンプレートコードを使用してfilename.jsファイル(存在しない場合)を作成します。
それだけです、簡単ですよね? これでキックできます。 親愛なる同僚のアドバイスと合理的な批判を喜んでいます。