反応機能部品とデコレータなしでMOBXを使用する -- reactjs フィールド と mobx フィールド と mobx-react フィールド 関連 問題

using mobx with react functional components and without decorators












10
vote

問題

日本語

反応内の機能コンポーネントを扱うようにMobXを取得しようとしています。デコレータを使用する必要なしにこれをやりたいです。 Create-React-Appを使ってアプリを設定し、依存関係としてMobxとMobX Reactを追加しました。 しかし、私は機能部品内で働く観察可能なものを得ることができないようです。

<事前> <コード> y_true = df['a','b','c']2

ボタンをクリックすると、観察可能な変更が変更されたためにコンポーネントがRERendedになると予想されますが、エラーが発生します。

<事前> <コード> y_true = df['a','b','c']3

私は機能的なコンポーネントの一部として、またはこのようにする前に観測可能な宣言を試みました:

<事前> <コード> y_true = df['a','b','c']4

しかし、両方の場合において、私は要素をRERNENDERに取得できなかったか、観察可能なものが実際に正しく設定されているかどうかわからなかった。

私がこのようなクラスとして全体を書いたらそれは完全に機能します

<事前> <コード> y_true = df['a','b','c']5
英語

I'm trying to get MobX to work with functional components in react. I want to do this without having to use decorators. I have set up an app with create-react-app, added MobX and MobX-react as dependencies. However, I can't seem to get observables working within functional components.

import React from 'react'; import { extendObservable } from 'mobx'; import { observer } from 'mobx-react';  const Test = () => {     extendObservable(this, {         button: false     });      const handleB1 = () => {         this.button = false;     }      const handleB2 = () => {         this.button = true;     }      const getButton2 = () => {         console.log('button2');         return (             <button type="button" onClick={handleB2}>Button 2</button>         );     };      const getButton1 = () => {         console.log('button1');         return (             <button type="button" onClick={handleB1}>Button 1</button>         );     };      return (         <div>             {this.button ? getButton1() : getButton2()}         </div>     ) };  export default observer(Test); 

Clicking the button I would expect the component to get rerendered due to the observable being changed, but I get an error:

× Error: [mobx] Invariant failed: Side effects like changing state are not  allowed at this point. Are you trying to modify state from, for example, the render  function of a React component? Tried to modify: ObservableObject@2.button 

I have tried declaring the observable as part of a functional component or before like this:

const buttonState = () => {     extendObservable(this, {         button: false     }); } 

but in both cases I could not get the component to rerender or i was not sure if the observable was actually correctly set.

If i write the whole thing as a class like this it works perfectly

import React from 'react'; import { extendObservable } from 'mobx'; import { observer } from 'mobx-react';  class Test extends React.Component {     constructor(props) {         super();         extendObservable(this, {             button: false         });     }      handleB1 = () => {         this.button = false;     }      handleB2 = () => {         this.button = true;     }      getButton2 = () => {         console.log('button2');         return (             <button type="button" onClick={this.handleB2}>Button 2</button>         );     };      getButton1 = () => {         console.log('button1');         return (             <button type="button" onClick={this.handleB1}>Button 1</button>         );     };      render = () => {         return  (         <div>             {this.button ? this.getButton1() : this.getButton2()}         </div>         )     } };  export default observer(Test); 
</div
        
       
       

回答リスト

14
 
vote
vote
ベストアンサー
 

反応において、機能性成分は持続的ではない。彼らは上から下に走り、いくつかのJSX、すすぎ、繰り返しを返します。

<事前> <コード> let i = 0; const FunctionalComp = (props) => { const foo = props.foo.toUpperCase(); return <span>Rendered {i++} times. {foo}</span>; }

この機能コンポーネントはすべて同期的に値 foo を作成してからスパンを返します。このコンポーネントの親が再レンダリングされると、このコンポーネントは同じように同じであるが、潜在的に新しい値を持つ。

それは決して何もすることはできません、そしてそれがそれが強力である理由です。そのため、機能コンポーネントを呼び出すことができる理由です。それはそれがそれに提供される値だけであるため、アプリケーションの残りの方向性を変えることになるため、同じ引数を考えると、この関数は残りの永遠のために同じ結果を生み出します。

予測可能=強力な。

今、クラスコンポーネントは永続状態を保持します。 IT構築、その状態、メソッド、およびプロパティを初期化してから、レンダリングしてJSXを返します。クラス(オブジェクト)はまだメモリ内に存在するので、すべての値とメソッドが存在します。

クラス成分の方法はそれほど予測できない。

<事前> <コード> class Foo { name = 'tommy'; getUpperName() { return this.name.toUpperCase(); } setName(name) { this.name = name; } }

Foo.getUpperName は、同じ引数で使用されるたびに同じ結果を生成することはありません(ヒントは引数を受け入れず、その結果を判断するためのコンテキストによって異なります)。そのため、他のアプリケーションは、<コード> Foo.name 、およびControl 99887665 の結果を潜在的に偶然に変更することができます。

クラスは独自の状態を更新し、それ自身とすべての子供コンポーネントがJSXリターンを再計算することができます。

平面矢印関数では、戻った後、存在するすべてが生成された戻り値と関数ステートメント(宣言)です。その間には何もありません。

これはすべて、機能コンポーネントには<コード> this がバインドされていません。 (それは機能的プログラミングではノーノーです。)州は決してありません。

だから機能コンポーネントの this では何もできず、それがこれらの値のそれぞれを再演奏するたびに観察可能な値を保持することはできません。上記の例では、 this を参照しても Test を参照しても、これは何が起こるでしょう。

  1. テストは、 foo1 として foo0 を作成します。
  2. テストはボタンをレンダリングします。
  3. テストは、 foo3 として、観測可能な値 foo2 を作成します。
  4. テストはボタンをレンダリングします。
  5. テストは、 foo5 として foo4 を作成します。
  6. テストはボタンをレンダリングします。
  7. それ以外に。

    Mobxでは、任意のデータ構造に住み、UIマークアップを返すレンダリング関数に渡される必要があります。

    <事前> <コード> this16

    foo7 nor <コード> foo8 は純粋であるため、素晴らしいパターンではありません。

    あなたはそのようなものをする必要があります:

    <事前> <コード> foo9

    また、これは理想的な実装ではありませんが、それはうまくいき、私は仕事をして、彼らが私にすることを支払うものに戻らなければなりません。 ;)

 

In React, functional components are not persistent. They run from top to bottom, return some JSX, rinse and repeat.

let i = 0;  const FunctionalComp = (props) => {   const foo = props.foo.toUpperCase();   return <span>Rendered {i++} times. {foo}</span>; } 

All this functional component will ever do is synchronously create the value foo and then return the span. When this component's parent re-renders, this component will do the same exact same, but with potentially new values.

It can never do anything else, and that is why it is powerful. That is why we can call it a functional component: Because it only depends on the values provided to it, because it does not cause side effects that would alter the direction of the rest of the application, and because given the same arguments, this function will produce the same result for the rest of eternity.

Predictable = powerful.

Now, a class component holds persistent state. It constructs, initializes its state, methods, and properties, and then renders and returns JSX. The class (object) still exists in memory, so all of the values and methods on it exist too.

The methods of class component are not so predictable.

class Foo {   name = 'tommy';    getUpperName() {     return this.name.toUpperCase();   }    setName(name) {     this.name = name;   } } 

Foo.getUpperName will not produce the same result every time it is ever used with the same arguments (hint: it doesn't accept any arguments and depends on the context around it to determine its result), so other pieces of the application may change Foo.name and, essentially, control Foo.getUpperName's outcome, potentially by accident.

The class can update its own state, causing itself and all children components to re-compute their JSX returns.

In a plain arrow function, after it returns, all that exists is the return value that it produces and the function statement (declaration). Nothing in between.

All this said, the functional component has no this bound to it. (That is a no-no in functional programming.) It will never have state.

So you can not do anything with this inside of a functional component and it can not hold observable values because every time it re-renders it would re-instantiate each of those values.

In your example above, even if this did refer to Test, this is what would happen:

  1. Test would create the observable value button as false.
  2. Test would render the button, which you would then click.
  3. Test would create the observable value button as false.
  4. Test would render the button, which you would then click.
  5. Test would create the observable value button as false.
  6. Test would render the button, which you would then click.

So on and so forth.

In MobX, your observables need to live on a persistent data structure and be passed into your render functions that return UI markup.

const store = observable({   name: 'tommy' });  const changeName = () => store.name = store.name.split('').reverse().join('');  const Foo = observer((props) => {   return (     <button onClick={changeName}>{store.name}'s button</button>   ) }); 

This is not a great pattern, as neither Foo nor changeName are pure, this code would work, at least.

You need to do something like so:

const store = () => {   const self = {};    self.actions = {     setName: action((name) =>  self.name = name);   }    return extendObservable(self, { name: 'tommy' }); }  const App = (props) => {     return <span><Foo store={store} /></span> }  const Foo = observer((props) => {   return (     <button onClick={props.store.actions.setName}>       {store.name}'s button     </button>   ) }) 

Again, this is not an ideal implementation, but it would work, and I am at work and have to get back to what they pay me to do. ;)

</div
 
 
 
 

関連する質問

6  React-Native-Navigationを使用して単一画面アプリをタブベースのアプリに変換する方法  ( How to convert single screen app to tab based app using react native navigation ) 
私は反応的なナビゲーションで手を尽くしていますが、簡単な問題で立ち往生しています。 アプリにはタブがないログインページがあります。 (Facebookのログインページとはるかに似ています)(イメージREF - 画像はちょうどアイデアを与えることです。イメー...

2  @コンピュータプロパティの周期検出エラー  ( Cycle detected error for computed properties ) 
私はMOBXの初心者です。私はMobXの計算されたプロパティを試していて、このエラーに走行していました <事前> <コード> [mobx] Cycle detected in computation Store@1.values: function () { ...

12  SessionStorageでMobx状態を保存する方法  ( How to save mobx state in sessionstorage ) 
この https://github.com/elgerlambert/redux-localstorage これはREDUX用ですが、MobX用に行います。そして好ましくはセッションストレージを使用したいと思います。最小限のボイラープレートでこれを達成する簡単...

1  mobx 'これはセッターアクションでは未定義です  ( Mobx this is undefined in setter action ) 
JSと mobx <コード> <コード> メソッドを使った最近のCreate-React-Appセットアップを使用しています。 <事前> <コード> import { observable, action, decorate } from 'mobx' ...

1  MobX-State-Tree Cloneも元のアイテムを変更しますか?  ( Mobx state tree clone also changes the original item ) 
次のモデルスニペットを持っています: <事前> <コード> nodeOrigin: types.maybe(types.reference(nodeState)), node: types.maybe(nodeState), と私は次の関数でノードの編集を...

0  クラス本体で宣言されている変数は、TypeScriptとMobXの関数内で未定義です。  ( Variable declared in class body is undefined within a function in typescript and ) 
JavaScriptに問題があるため、MobxとTypescriptのシンプルなカウントストアを書いています。これはフルコードです: <コード> import { observable, autorun, computed, action } from "...

1  SORTABLE JSをMOBXに反応させる  ( React sortable js with mobx ) 
React-SoortableJSを使用してMobX Storeからのコンピュータアレイ(レイヤーアレイ)とソート可能なコンポーネント(ReactSortable)をレンダリングする必要がある機能コンポーネントを構築しています。アプリケーションがロードされた...

0  React Router UseHistory Go機能が正しく機能していません  ( React router usehistory go function not working properly ) 
TyssScriptアプリとReact-router-DOM 5.1.2とMobXを使用しています。それはユースシリストリーフックを使います。モーダル内のフォーム送信を処理してから、前のページに戻るためにGO(0)を実行するコードがあります。問題は、ブラウザ...

7  反応:目に見えない表にコンポーネントをレンダリングしないでください  ( React dont render components in table who arent visible ) 
私はgt; 30行とgt; 50列のテーブルを持っています。各行と各セルは、それらを操作して行動を変更してデータの変更に基づいて見えるので、特定の反応成分です。 だから私のコンポーネントのhirachyは次のようになります: <コード> [HttpGet] ...

2  React + Mobx、ユーザーの認証、レンダリングエラー  ( React mobx user authantication render error ) 
私は私の状態管理に inf6 を使用しています、そして私は inf7 にもいくつかの情報を保存します。 これは私のMobxStoreがどのように見えるものです: <コード> inf8 アイデアは、ページのリダイレクトを介した inf9 を...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有