You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React共享状态下JSON/YAML编辑器无法新增键值的问题解决需求

JSON与YAML编辑器共享React状态时无法新增键值对的解决方案

问题描述

当JSON编辑器与YAML编辑器共享并更新同一React状态时,无法在任一编辑器中新增键值对,需要实现双向实时同步,支持新增、修改键值对。

组件代码


父组件(通过props传递JSON数据给子组件)

import * as React from 'react';
import Editors from './Editors';

const jsonData = {
  name: 'name',
  email: 'email',
  phone: [123, 234, 345],
  location: 'location',
  country: 'country',
  show: true,
};

export default function App() {
  return (
    <div>
      <Editors jsonData={JSON.stringify(jsonData, null, 4)} />
    </div>
  );
}

子组件(接收props中的JSON数据)

import * as React from 'react';
import { useState, useEffect } from 'react';
import YAML from 'yaml'; // 官方YAML包
import { load } from 'js-yaml'; // JavaScript版官方YAML解析包
import Editor from '@monaco-editor/react';

export interface Iprops {
  jsonData: string;
}

function Editors(props: Iprops) {
  const [data, setData] = useState('');

  useEffect(() => {
    setData(props.jsonData);
  }, [props]);

  return (
    <React.Fragment>
      <div>
        <h5>JSON:</h5>
        <Editor
          height="300px"
          defaultLanguage="json"
          value={data}
          onChange={(val) => setData(val)}
          theme="vs-dark"
        />
      </div>

      <div>
        <h5>YAML:</h5>
        <Editor
          height="300px"
          defaultLanguage="yaml"
          value={YAML.stringify(load(data))} // load将JSON字符串解析为普通对象
          onChange={(val) => setData(JSON.stringify(load(val), null, 4))}
          theme="vs-dark"
        />
      </div>
    </React.Fragment>
  );
}

export default Editors;

需求目标

  • 维护统一状态,支持在JSON/YAML编辑器中新增、修改键值对
  • 实现JSON与YAML编辑器的实时转换同步

解决方案

原实现的核心问题是将字符串作为状态载体,频繁的JSON/YAML解析转换容易导致状态覆盖或解析失败,进而无法新增键值对。以下是优化后的实现:

修改后的子组件代码

import * as React from 'react';
import { useState, useEffect } from 'react';
import { load, dump } from 'js-yaml';
import Editor from '@monaco-editor/react';

export interface Iprops {
  jsonData: string;
}

function Editors(props: Iprops) {
  // 以JS对象作为核心状态,避免字符串解析的不稳定问题
  const [dataObject, setDataObject] = useState<Record<string, any>>({});

  // 初始化从props加载并解析数据
  useEffect(() => {
    try {
      const parsed = JSON.parse(props.jsonData);
      setDataObject(parsed);
    } catch (e) {
      console.error('初始化JSON解析失败:', e);
    }
  }, [props.jsonData]);

  // JSON编辑器变更处理:解析输入并更新核心状态
  const handleJsonChange = (val: string | undefined) => {
    if (!val) return;
    try {
      const parsed = JSON.parse(val);
      setDataObject(parsed);
    } catch (e) {
      // 保留错误输入,不重置状态
      console.error('JSON解析失败:', e);
    }
  };

  // YAML编辑器变更处理:解析输入并更新核心状态
  const handleYamlChange = (val: string | undefined) => {
    if (!val) return;
    try {
      const parsed = load(val);
      if (typeof parsed === 'object' && parsed !== null) {
        setDataObject(parsed);
      }
    } catch (e) {
      // 保留错误输入,不重置状态
      console.error('YAML解析失败:', e);
    }
  };

  return (
    <React.Fragment>
      <div style={{ marginBottom: '20px' }}>
        <h5>JSON编辑器:</h5>
        <Editor
          height="300px"
          language="json"
          value={JSON.stringify(dataObject, null, 4)}
          onChange={handleJsonChange}
          theme="vs-dark"
        />
      </div>

      <div>
        <h5>YAML编辑器:</h5>
        <Editor
          height="300px"
          language="yaml"
          value={dump(dataObject, { indent: 2 })}
          onChange={handleYamlChange}
          theme="vs-dark"
        />
      </div>
    </React.Fragment>
  );
}

export default Editors;

解决思路说明

  1. 核心状态用JS对象:避免字符串解析转换带来的错误和状态覆盖问题,所有编辑器的内容都基于该对象生成
  2. 添加错误捕获:无效输入(如不合法的JSON/YAML)不会重置状态,保留用户输入内容
  3. 稳定的转换方法:使用js-yaml的dump方法生成规范YAML,兼容性和可读性更好
  4. 独立的变更处理:每个编辑器的变更逻辑独立,确保输入内容能正确同步到核心状态

内容的提问来源于stack exchange,提问作者Ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 16:05:39