首页 > 解决方案 > 使用 react-spring 到 XMasonry 布局创建和删除项目列表时添加动画时出错

问题描述

我正在制作一个简单的类似 Google Keep 的笔记反应应用程序。我XMasonry用于布局。我想添加动画react-spring,使其在删除和创建项目列表时淡入淡出。但我不断收到错误,为什么要让 Xmasonry 与 react-spring 一起工作。我在这里想念什么?我应该使用useStringor 吗Transition?(https://prnt.sc/t9y1ox


const InitialNotes = [
  {
    key: 1,
    title: "Delegation",
    content:
      "Q. How many programmers does it take to change a light bulb? A. None – It’s a hardware problem",
  },
  {
    key: 2,
    title: "Loops",
    content:
      "How to keep a programmer in the shower forever. Show him the shampoo bottle instructions: Lather. Rinse. Repeat.",
  },
  {
    key: 3,
    title: "Arrays",
    content:
      "Q. Why did the programmer quit his job? A. Because he didn't get arrays.",
  },
  {
    key: 4,
    title: "Hardware vs. Software",
    content:
      "What's the difference between hardware and software? You can hit your hardware with a hammer, but you can only curse at your software.",
  },
];
function App() {

    const [notes, setNotes] = useState(InitialNotes);


    function addNoteHandler(note) {
        setNotes((prevNotes) => {
            return [...prevNotes, note];
        });
    }

    function onEditNote(idx, toUpdateNote) {
        const newNotes = [...notes];
        newNotes[idx] = toUpdateNote;
        setNotes(newNotes);
    }
    function deleteNote(id) {
        setNotes((notes) =>
            notes.filter((note, idx) => {
                return note.key !== id;
            })
        );
    }

    return (
        <div className="App">
            
            <AddNote addNoteHandler={addNoteHandler} />
            <div className="container">
              <XMasonry>
                    <Transition
                        items={notes}
                        keys={(note) => note.key}
                        from={{ opacity: 0 }}
                        enter={{ opacity: 1 }}
                        leave={{ opacity: 0 }}
                    >
                        {(note) => (styles) => (
                            <animated.div styles={styles}>
                                <XBlock>
                                    <Note
                                        id={note.key}
                                        key={note.key}
                                        title={note.title}
                                        content={note.content}
                                        deleteNote={deleteNote}
                                        onEditNote={onEditNote}
                                    />
                                </XBlock>
                            </animated.div>
                        )}
                    </Transition>
                </XMasonry>
            </div>

            
        </div>
    );
}
function Note(props) {
    const initialNote = {
        id: "",
        title: "",
        content: "",
    };
    const [IsEdit, setIsEdit] = useState(false);
    // const [Zindex, setZindex] = useState({ zIndex: "1" });
    // const [isDelete, setIsDelete] = useState(false);

    const [note, setNote] = useState(initialNote);

    function AutoResize() {
        this.style.height = "auto";
        this.style.height = this.scrollHeight + "px";
    }
    function setAutoResize() {
        const textarea1 = document.querySelector("#auto-resizing1");
        console.log(textarea1);
        textarea1.addEventListener("input", AutoResize, false);
    }

    useEffect(() => {
        const updateNote = {
            id: props.id,
            title: props.title,
            content: props.content,
        };
        setNote(updateNote);
        if (IsEdit) setAutoResize();
    }, []);

    function onDelete(e) {
        // setIsDelete(true);
        console.log("Delete iTem");
        props.deleteNote(props.id);

        e.preventDefault();
    }

    function onChange(e) {
        const { name, value } = e.target;
        setNote((prevNote) => {
            return { ...prevNote, [name]: value };
        });
    }

    const onEdit = () => {
        return (
            <div className="note">
                <input
                    type="text"
                    name="title"
                    value={note.title}
                    onChange={onChange}
                />
                <textarea
                    id="auto-resizing1"
                    type="text"
                    name="content"
                    value={note.content}
                    onChange={onChange}
                />
                <button
                    onClick={() => {
                        props.onEditNote(props.id, note);
                        setIsEdit(false);
                    }}
                >
                    <SendIcon />
                </button>
                <button onClick={() => setIsEdit(false)}>
                    <CloseIcon />
                </button>
            </div>
        );
    };

    const onShow = () => {
        return (
            <div className="note">
                <h1>{props.title}</h1>
                <p>{props.content}</p>
                <button onClick={onDelete}>
                    <DeleteIcon />
                </button>
                <button onClick={() => setIsEdit(true)}>
                    <EditIcon />
                </button>
            </div>
        );
    };

    return IsEdit ? onEdit() : onShow();
}

这是我的代码:https ://codesandbox.io/s/google-keep-note-ny71j?file=/src/App.js

标签: masonryreact-spring

解决方案


我试图修复你的例子。第一个问题,XMasonry 期望将 XBlocks 作为它的孩子。它在你的例子中得到了 div 。Transition如果它的孩子是 div ,你会得到与普通 XMasonry 类似的错误。

第二个问题是Transition处理安装和卸载本身。XMasonry 正在尝试做完全相同的事情,期望在渲染过程开始时立即获取所有组件。所以在我看来,你不能以这种方式将 react-spring 与 XMasonry 一起使用。

您可以在 XMasonry 中更改动画。我在 index.css 中添加了不透明度更改作为样式。

@keyframes comeIn {
  0% {
    transform: scale(0);
    opacity: 0;
  }
  75% {
    transform: scale(1.03);
    opacity: 0.5;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.xmasonry .xblock {
  animation: comeIn ease 0.5s;
  animation-iteration-count: 1;
  transition: left 0.3s ease, top 0.3s ease;
}

不幸的是,据我所知,您只能通过这种方式更改输入动画。但总比没有好。

https://codesandbox.io/s/google-keep-note-u0p5d?file=/src/index.css

如果我是你,我会问一种在 XMasonry 的 github 页面上添加离开动画的方法。


推荐阅读