muuri-react with Redux causes “Invariant failed: The item has not been setted yet”

I am passing a list of objects to muuri-react to display in a draggable grid layout and it works fine when I pass an explicitly defined list of objects, but when I use a redux selector to get the data it breaks even though it’s the same data.

Here is an example that reproduces this: https://codesandbox.io/s/agitated-montalcini-rbdso?file=/src/components/pages/Notes.js

I render two Muuri grids one with with notes1 and one with notes2 which are identical objects, but somehow notes1 works fine and notes2 doesn’t render properly (not draggable) and causes the error Invariant failed: The item has not been setted yet if you try navigating to another tab like Reminders. I check that notes1 and notes2 are equal with lodash console log.

import React, { useEffect } from "react";
import { MuuriComponent } from "muuri-react";
import styled from "styled-components";
import { useSelector, useDispatch } from "react-redux";
import { fetchNotes } from "../../state/slices/notesSlice";
import _ from "lodash";

const Notes = () => {
  const dispatch = useDispatch();

  // Fetch notes
  useEffect(() => {
    dispatch(fetchNotes());
  }, []);

  let notes1 = [
    {
      id: "1",
      title: "Title 1",
      text:
        "Text 1 - Est libero a lorem curabitur auctor at viverra ipsum id euismod condimentum dolor vel sit nullam libero nec"
    },
    { id: "2", title: "Title 2", text: "Text 2 - Auctor dolor vitae nullam" },
    {
      id: "3",
      title: "Title 3",
      text:
        "Text 3 - Viverra nunc enim adipiscing lorem laoreet id nec condimentum est odio dolor sagittis in libero nullam ipsum"
    }
  ];
  let notes2 = useSelector((state) => Object.values(state.notes.byId));

  console.log("_.isEqual(notes1, notes2)?", _.isEqual(notes1, notes2));

  return (
    <StyledNotes>
      <MuuriWrapper>
        <MuuriComponent dragEnabled dragFixed>
          {notes1.map((note, i) => (
            <StyledNote key={i}>
              <h3>{note.title}</h3>
              <div>{note.text}</div>
            </StyledNote>
          ))}
        </MuuriComponent>
      </MuuriWrapper>
      <MuuriWrapper>
        <MuuriComponent dragEnabled dragFixed>
          {notes2.map((note, i) => (
            <StyledNote key={i}>
              <h3>{note.title}</h3>
              <div>{note.text}</div>
            </StyledNote>
          ))}
        </MuuriComponent>
      </MuuriWrapper>
    </StyledNotes>
  );
};

const MuuriWrapper = styled.div`
  border: 1px solid black;
`;

const StyledNotes = styled.div`
  padding: 30px;
`;

const StyledNote = styled.div`
  border: 1px solid ${({ theme }) => theme.border};
  border-radius: ${({ theme }) => theme.borderRadius};
  background-color: ${({ theme }) => theme.background};
  max-width: 250px;
  min-width: 250px;
  overflow-y: hidden;
  padding: 15px;
  margin: 15px;

  &.muuri-item-dragging {
    z-index: 1;
  }
`;

export default Notes;

Answer

If you log notes2, you will see that it changes from the length of 0 (start request), to the length of 3 (fully requested)

I see that the issue is due to the dynamic aspect of notes2, while it seems that the murri lib will load well for the static one (notes1)

So a quick fix could be to make sure to load MurriGrid after notes2 is fully requested, so it will avoid first time load for the init one (length of 0) then rerender to fully-loaded one (length of 3) – which caused unexpected behavior

      {notes2.length && (
        <MuuriWrapper>
          <MuuriGrid>
            {notes2.map((note, i) => (
              <StyledNote key={i}>
                <h3>{note.title}</h3>
                <div>{note.text}</div>
              </StyledNote>
            ))}
          </MuuriGrid>
        </MuuriWrapper>
      )}

Edit reverent-faraday-nlwlt