ReactJS组件渲染顺序错误

3

这个问题有点冗长,但我希望你能明确了解发生了什么...

我正在为我们公司构建一个任务管理器桌面应用程序(Electron),我遇到了奇怪的行为。 任务管理器有6列(每个员工一列),包含要完成的任务的垂直列表。 它包括拖放功能,以便您可以对任务进行排序。

我正在使用Dragula处理拖放部分,然后按顺序从上到下收集所有任务的ID号码,存储在一个数组中。

我正在使用PouchDB更新数据库并同步其他正在运行的应用程序。

对于Dragula / PouchDB方面,我正在使用以下代码:

var containers = [];
containers.push(ReactDOM.findDOMNode(this.refs.taskContainer));

var drake = Dragula(containers);
drake.on('drop', function(el, target, source, sibling) {

  // Get Desired Order of IDs
  for(i = 0; i < source.children.length; i++) {
    ids.push(source.children[i].id);
  }

  // Loop through IDs, write an "order" to tasks in PouchDB Database ("TaskData").
  // TaskData's replication is "live" so it automatically syncs to the DB.
  for(i = 0; i < ids.length; i++) {
    TaskData.get(ids[i]).then(function(doc) {   
      doc.order = ids.indexOf(doc._id);
      TaskData.put(doc).catch(function(err) {
        console.log(err);
      });
    });
  }

});

此时,我的TaskData现在有一个新的“order”关键字,具有所需的值。现在,我需要按顺序渲染ReactJS组件。 从props中获取任务(从TaskData刷新)并过滤出所需内容:
var tasks = this.props.tasks.filter(function(task) {
  if(task.archive !== 1) {
    return true
  }
});

我使用lodash.js按照上述顺序号对任务进行排序,并将排序后的数据映射到React组件中:

tasks = _.sortBy(tasks, 'order').map(function(task) {
  return <Task key={task.id} order={task.order} ...more props />
});

太好了,我的任务已按顺序呈现,一切看起来都很不错。

现在有个问题...

当我将我的任务从["1", "2", "3", "4"]拖放重新排序为["4", "1", "2", "3"]时,实际上得到的是["3", "4", "1", "2"]。 任务会移动和更新(因为上面的Dragula / PouchDB代码)。 奇怪... 我在Dev Tools中键入location.reload(),令人惊讶的是,任务现在按照我最初想要的顺序排序:["4", "1", "2", "3"]

再试一次,我将任务从["1", "2", "3", "4"]移动到["1", "3", "2", "4"],任务重置回["1", "2", "3", "4"]。 再次使用location.reload(),任务现在按照我想要的顺序排序:["1", "3", "2", "4"]

尝试调试后,我发现如果禁用_.sortBy函数,则任务在被拖放后保持不变(尽管它们一开始就是无序的)。任务移动到所需位置并具有所需的顺序号。
我还发现,如果禁用PouchDB的.put(),并使_.sortBy正常工作,它也可以正常工作,但数据不会写入服务器,并且顺序号不会因此更新。
也许我只是盯着这段代码看了太久,但我无法弄清楚为什么任务会跳来跳去。 有人有什么想法吗?
谢谢您的帮助!

可能是 http://stackoverflow.com/questions/34010410/reactjs-sorting-an-array-of-objects-in-state 的重复。 - Alf
是的,它非常相似。希望我们中的一个人能得到答案,因为这可能会帮助另一个人。 - Justin
是的,这非常类似于我之前发布的帖子。从我所看到的,我们的一致性在于使用dragula、项目排序和重新渲染组件。问题:你没有保存重新排序的项目状态,对吧?你只是获取任务列表,然后进行排序/映射到新组件,是吗? - BDUB
@BDUB 我已经尝试了很多次解决这个问题。其中一种方法涉及获取任务属性,修改顺序并将其存储为状态,但我也没有成功。目前,正如上面的代码所示,我传递了任务属性,然后修改了顺序并在渲染函数中映射组件。理想情况下,我会将它们移动到单独的函数中 - 但我首先要让组件正常工作。 - Justin
@Phillips126 你看看这个:https://github.com/bevacqua/dragula/issues/188#issuecomment-139914022。我有个很好的预感 dragula-react 和 react 不太相容。可能情况是在 react 渲染组件后,dragula 又重新排列了项。这是我正在追求的线索:在 drop 事件中进行所有数据操作,然后在 dragend 事件中进行渲染,以确保 dragula 不再干扰。我会通知你的。 - BDUB
@BDUB 不错的发现!那个帖子完美地解释了我的应用程序中正在发生的事情。我有一种预感,Dragula在我的数据更新后强制执行了顺序。让我知道你的进展如何! - Justin
1个回答

0

我通过实现uuid成功地让我的工作。以下是代码片段:

// Import the code
import uuid from 'uuid';

// My dummy component
<Messages>
  <ul>
    {messages.map(({ value, signature }) => (
      <Message 
        value={value}
        key={uuid.v4()} // use the uuid as the unique key
        from={signature}
        onMessageRecieved={this.handleMessageRecieved} />
    ))}
  </ul>
</Messages>

查看这些笔记以获取有关实现的更多信息。 https://survivejs.com/react/getting-started/implementing-notes/

感谢@Alf提供此链接。帮助我解决了我的问题,请参见@Dmitri Zaitsev的答案。

愉快编码 =)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接