2016-08-26 4 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)]]))) 

자신의 크기를 표시하는 구성 요소를 다시 렌더링하기 위해 수행, 로그 메시지는 구성 요소가 불필요하게 모든 시간을 다시 렌더링되는 의미 지속적으로 인쇄됩니다. 숫자 또는 문자열 만 반환하면 로그는이 시나리오에서 의도 한대로 두 번 나타납니다.

이 이유가 무엇인가요? 아마도 clojure 스크립트 아톰을 새로운 벡터 (동일한 값을 포함하고 있음)로 업데이트하는 것이 내부적으로 다른 JavaScript 객체를 삽입하여 원자를 변경한다는 의미일까요? 가치를 두는 것은 관찰 할 수없는 변화를 가져 오지 않습니까? 그냥 추측 ... *

어쨌든 - 실제 사용 케이스의 경우 벡터의 스팬 크기를 절약하는 것이 더 낫습니다.이 방법이 있습니까?

나는 캠을 this 질문에 주어진 답변을 강화하려고 할 때 이것을 가로 질렀습니다.


* 이후 JS에서 : ({} === {}) // false

+0

나는 그것을 테스트 할 수있는 설치물이 아니지만 계산 된 크기를'get-real-size'에 로깅 해보십시오. 내 생각 엔 끊임없이 변화하고있다.그것은 그것이 자신의 크기가되고 다른 값을 표시 할 때마다 너비가 변경되어 다시 렌더되도록하고 너비가 다른 새로운 크기로 새 참조를 얻게되기 때문입니다. –

+0

아니요, 저는 너무 추측했다. 함수가 더미 일 때도 마찬가지입니다 :'(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 :

ratoms의 경우? 이전 값과 관련하여 새로운 값이 변경되었는지를 결정하기 위해 (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"는 항상 같은 객체이고, 동일한 값을 포함하는 두 개의 벡터는 서로 같은 객체가 아니라는 내부 기본 데이터 표현이 있다고 생각합니다.

확인 : 시약 원자가 아닌 일반 원자로는 벡터 아이덴티티가 아님에도 불구하고 문자열 재설정이 원자 재설정을 통해 유지된다는 것을 알 수 있습니다.

(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'는 같은 행동을 보입니다 . 이것이 버그, 또는 반응과 람의 의도적 인 차이라고 생각합니까? –

관련 문제