react 是一个处理复杂数据导致 UI 变化的一个好工具,但是工具虽好,但是不能看啥都是钉子。在我们常见的操作中,大多数情况交互并不是很重,这种情况下,用传统的 rails view 来生成界面,实际上是个不错的选择。
平时在处理 form 的时候,我一般不会完全用 react 处理表单,之后 提交一个 formdata, 而是选择靠 rails 来生成 form 进行快速提交,这样就不需要又写界面又写 rails api。
今天遇到的情况比较有典型性:
大概是表单里有一个字段存一个 json,这个 json 本身会有复杂的配置,有很多操作都影响着这个 json 的生成,
因为操作比较多,于是这块当然用 react_component 比较好实现,但是个 json 本身是由表单最外层的一个 category 选择框来确定不同的模型的,同时这两个界面模块中间还隔了一些表单的其他内容,这些内容因为业务原因,必须放在 category 和 react 组件的中间
平常有两种方案能解决这个问题:
这种方式其实就是走 rails api 的方式了,但是由于这里我已经用 rails view 实现了其他表单属性的界面和校验,再改一次很麻烦
这种方式处理起来比较简单,即将 react_component 外层用 一个 div 包起来,之后 change 回来的 js 先清空他,在 render escape 一个 react_component,这种方式倒是比较简单,同时也不改其他的代码,只是要多调用一下服务端,感觉有点没必要。
最后决定不如用 stimulusjs 来控制 react_component 的 props 好了,这样就可以直接通过 js 而不过后端来控制显示了。
这是相关的代码逻辑
import {Controller} from 'stimulus'
export default class extends Controller {
static targets = ["dropdown", "metaArea"]
connect(){
this.changeMetaAreaAttribute();
}
readDropdownValue(){
return this.dropdownTarget.value
}
needShowMetaArea(){
return this.dropdownTarget.value === 'Conversations::QuestionConversation'
}
changeMetaAreaAttribute(){
// 注意此处, 因为 react_component 实际存储 props 本身是string 型, 所以需要转化一下
let json = JSON.parse(this.metaAreaTarget.dataset.reactProps)
json["category"] = this.readDropdownValue()
this.metaAreaTarget.dataset.reactProps = JSON.stringify(json)
ReactRailsUJS.mountComponents() // 注意此处, 再修改完毕之后, 需要让 React Component 重新渲染一下
}
}
之后此处的 react_component,需要多传一个参数,让 stimulusjs 能够指定到 target
<%= react_component "AdminMetaEditors", {init_meta: chat_task.meta, category: chat_task.category}, {data: {chat_workflow_category_target: 'metaArea'}} %>
这样就能够 react_component 和 stimulus 混用了
总结: