0

我有一些组件嵌套在一个更大的“控制器”组件中。

整个演示应用程序如下。还有一个StackBlitz

import React, { useState } from 'react';
import CodeEditor from './CodeEditor';
import './style.css';

const PostEditor = ({ value, onChange }) => {
  return (
    <>
      {value && (
        <>
          <CodeEditor value={value} onChange={value => onChange(value)} />
        </>
      )}
    </>
  );
};

const Wrapper = ({ post, updatePostProperty }) => {
  return (
    <>
      <h2>Selected post: {post && post.title}</h2>
      {post && post.title && (
        <PostEditor
          value={post.title}
          onChange={value => {
            console.log('update title->', value);
            updatePostProperty(post.id, 'title', value);
          }}
        />
      )}
      {post && post.subTitle && (
        <PostEditor
          value={post.subTitle}
          onChange={value => {
            console.log('update subTitle->', value);
            updatePostProperty(post.id, 'subTitle', value);
          }}
        />
      )}
    </>
  );
};

export default function App() {
  const [posts, setPosts] = useState([
    { id: 1, title: 'post no 1', subTitle: 'subtitle no 1' },
    { id: 2, title: 'post no 2', subTitle: 'subtitle no 2' },
    { id: 3, title: 'post no 3', subTitle: 'subtitle no 3' }
  ]);
  const [post, setPost] = useState();

  const updatePostProperty = (id, property, value) => {
    const newPosts = [...posts];
    const index = newPosts.findIndex(post => (post.id === id));
    newPosts[index] = {
      ...newPosts[index],
      [property]: value
    };
    setPosts(newPosts);
  };
  return (
    <div>
      <ul>
        {posts &&
          posts.length > 0 &&
          posts.map((post, index) => (
            <li
              style={{ cursor: 'pointer' }}
              onClick={() => {
                setPost(post);
              }}
            >
              {post.title} - {post.subTitle}
            </li>
          ))}
      </ul>

      <Wrapper post={post} updatePostProperty={updatePostProperty} />
    </div>
  );
}

当组件触发包装器时,App组件承载updatePostProperty传递给Wrapper使用它的组件的组件。PostEditoronChangeCodeEditorCodeMirror

这里的问题是,在您单击其中一个帖子并编辑标题和副标题后,标题会恢复为初始值。

场景:
点击第一个帖子并尝试编辑标题。!在标题中添加一个。您会看到列表中的帖子已更新。
通过向其添加字符来编辑副标题后,您将看到标题恢复到组件!中的先前状态(没有 )App

为什么反应做这个“恢复”更新?

展示不良反应行为的 gif


更新

新的 StackBlitz

  • useEffect在更改原始posts数组之前,我对要使用的脚本进行了一些调整。
  • 我添加了一个常规input元素以查看问题是否仍然存在。似乎该问题已通过常规inputs 解决。

但是,我希望有人能就为什么 CodeMirror 的连接方式仍然存在问题。

4

2 回答 2

1

在里面updatePostProperty你正在更新错误的对象。

您正在更新:

posts[index] = {
  ...newPosts[index],
  [property]: value
};

但是你想更新newPosts,所以你必须这样做:

newPosts[index] = {
  ...newPosts[index],
  [property]: value
};
于 2021-07-26T20:55:11.470 回答
0
  1. 它需要newPosts代替posts
  2. 无需解构
  3. 你在=这里使用 1newPosts.findIndex(post => (post.id = id));假设是 2==喜欢newPosts.findIndex(post => (post.id == id));

签出此代码

  const updatePostProperty = (id, property, value) => {
    const newPosts = [...posts]; 
    const index = newPosts.findIndex(post => (post.id == id)); 
    newPosts[index][property] = value
    setPosts(newPosts);
  };
于 2021-07-26T21:15:17.247 回答