ClojureScript中react-pivottable的PivotTableUI界面修改后不更新状态
问题:React-PivotTableUI组件状态修改后数据不更新
组件已成功加载初始数据,但通过界面修改状态后,数据并未发生变化,现象如下:

相关代码:
(ns ui.pivottable.react-pivottable (:require ["react-pivottable/PivotTableUI" :default PivotTableUI] ["react-pivottable/TableRenderers" :as TableRenderers] ["react-plotly.js" :default Plot] ["react-pivottable/PlotlyRenderers" :as create-plotly-renderers] [reagent.core :as r])) (defn pivottable [] (let [state (r/atom {:data (clj->js [[:name "Alice" :age 30 :city "New York"] [:name "Bob" :age 35 :city "Chicago"] [:name "Charlie" :age 40 :city "New York"]]) :aggregator-name "Count" :renderer-name "Table" :rows [:name] :cols [:age]}) component (r/adapt-react-class PivotTableUI) plotly-renderers (create-plotly-renderers Plot) table-renderers TableRenderers params {:rows [:name] :cols [:age] :on-change #(do (reset! state (.assign js/Object #js {} %)) ;; (reset! state (clj->js %) another try, it's the same) (.log js/console @state)) :renderers (.assign js/Object #js {} plotly-renderers table-renderers)}] [component (merge @state params)]))
问题原因
- 固定参数覆盖动态状态:代码里
params包含了固定的:rows和:cols,每次组件渲染时merge @state params会把@state中更新后的rows/cols覆盖回初始值,界面操作的变更根本没生效。 - 状态类型不兼容:
on-change里用Object.assign生成的JS对象直接存入Reagent atom,Reagent对原生JS对象的变更追踪不敏感,可能导致状态更新了但组件没触发重渲染。
解决方案
修改后的代码:
(ns ui.pivottable.react-pivottable (:require ["react-pivottable/PivotTableUI" :default PivotTableUI] ["react-pivottable/TableRenderers" :as TableRenderers] ["react-plotly.js" :default Plot] ["react-pivottable/PlotlyRenderers" :as create-plotly-renderers] [reagent.core :as r] [cljs-bean.core :refer [->clj]])) ;; 引入cljs-bean转换JS对象到CLJS结构 (defn pivottable [] (let [state (r/atom {:data (clj->js [[:name "Alice" :age 30 :city "New York"] [:name "Bob" :age 35 :city "Chicago"] [:name "Charlie" :age 40 :city "New York"]]) :aggregator-name "Count" :renderer-name "Table" :rows [:name] :cols [:age]}) component (r/adapt-react-class PivotTableUI) plotly-renderers (create-plotly-renderers Plot) table-renderers TableRenderers renderers (.assign js/Object #js {} plotly-renderers table-renderers)] [component (merge @state {:on-change #(reset! state (->clj %)) ;; 转换为CLJS map确保状态追踪 :renderers renderers})]))
关键修改说明
- 删掉
params里的:rows和:cols,让@state中存储的动态状态能正常传递给组件,不再被固定值覆盖。 - 用
cljs-bean的->clj把on-change回调返回的JS对象转换成CLJS的map结构,Reagent能准确追踪这个结构的变化,触发组件重渲染。 - 把
renderers单独提取出来,避免每次渲染重复创建相同对象,优化性能。
内容的提问来源于stack exchange,提问作者Diego Peñalver Montero
相关产品推荐
相关产品推荐

