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 混用了
总结: