2016-08-26 6 views
1

以下の試薬成分を検討してください。スパン要素の実サイズに基づいてローカル状態のアトムを更新するref関数を使用します。これはget-real-sizeの実装はベクトルを返す場合クロージャレットの原子に変化すると、試薬成分が再現されますか?

(defn show-my-size-comp [] 
    (let [size (r/atom nil)] 
    (fn [] 
     (.log js/console "log!") 
     [:div 
     [:span {:ref (fn [el] 
         (when el (reset! size (get-real-size el))))} 
     "Hello, my size is:" ] 
     [:span (prn-str @size)]]))) 

独自のサイズの表示コンポーネントを再レンダリングするために行われ、ログメッセージは、コンポーネントが不必要にすべての時間を再レンダリングされている意味、常に印刷されます。数値または文字列を返すだけの場合、ログはこのシナリオで意図したように2回しか表示されません。

この理由は何ですか?それは、おそらく、新しいベクトル(同じ値を含む)でclojureスクリプトアトムを内部的に更新することは、別のJavaScriptオブジェクトをそこに置くことを意味し、アトムを変更するでしょうか?価値を置くことは観察可能な変化をもたらさないのに対し、ちょうど投機... *

とにかく - 実際の使用例では、ベクトルのスパンのサイズを保存する方が確かに良いでしょう。これを達成する方法はありますか?

私はこれを渡り、this質問で与えられた答えを強化しようとするときに。


*以来、JSで:({} === {}) // false

+0

私はそれをテストできますが、計算されたサイズを 'get-real-size'で記録しようとしています。私の推測では、それは絶えず変化しています。それは、それが自分のサイズになり、異なる値を表示するたびに、幅が変わって再レンダリングされ、新しい幅で新しいサイズで新しいrefを取得するからです。 –

+0

nope、私あまりにも推測しました。関数がダミーのときも同じです: '(defn get-real-size [_] [0 0])' –

答えて

2
あなたは not=チェックで問題を回避することができ

:私は理由はベクトルが異なるすべき理由何のためにあるのかわからないんだけど

   (fn [el] 
        (when el 
        (let [s (get-real-size el)] 
         (when (not= s @size) 
         (reset! size s))))) 

その他の値。

+0

これは私が最後にしたものです。 –

3

私はベクトルが文字列/数字とは異なる動作をする理由について答えがあると思います。試薬は、identical?が古い値と新しい値との間で偽を返すとき、試薬原子を「変更された」ものとしてカウントし(したがって、それに依存する成分を更新する)。サブヘッド「変更済み」を参照してください。 in this tutorial

ラットの場合、古い値に関して新しい値が変更されたかどうかを判断するために使用されます(ratom内の値)。

しかし、identical?は、ベクトルと文字列/ intの動作が異なります。あなたがCLJまたはcljsのREPLのいずれかを起動した場合、あなたはそれを参照してくださいよ:

(identical? 1 1) 
;; true 
(identical? "a" "a") 
;; true 
(identical? [1] [1]) 
;; false 
(identical? ["a"] ["a"]) 
;; false 

をあなたが何をするかidentical?hereを見れば、あなたはその引数が同じオブジェクトであれば、それはテストすることがわかります 。私は基本的な内部データ表現は、クロージャーでは、 "a"は常に同じオブジェクトであり、同じ値を含む2つのベクトルは互いに同じオブジェクトではないと考えています。

確認:試薬原子ではなく普通のものでは、文字列の同一性が原子のリセット全体で保持されているのに対し、ベクトルの同一性は保持されていないことがわかります。

(def a1 (atom "a")) 
(let [aa @a1] (reset! a1 "a") (identical? aa @a1)) 
;; true 
(def a2 (atom ["a"])) 
(let [aa @a2] (reset! a2 ["a"]) (identical? aa @a2)) 
;; false 
+0

はいこれは正解です。 https://github.com/reagent-project/reagent/blob/master/CHANGELOG.md#060-alphaによると、私は試薬がこの場合に等価を使用することを望んだが、「0.6.0-rc」は同じ挙動を示す。これはバグだと思うのですか、あるいは反応とラットの意図的な違いでしょうか? –

関連する問題