0

我正在尝试使用 Framer Motion 在 React 中制作组件轮播。孩子AnimatePresence需要一个键,所以我决定传递一个页面状态作为键。但是,这样做会使我尝试渲染的组件重复。我认为这是因为密钥最终会被重用,所以我制作了一个函数,生成一个随机字符串用作密钥,但这也复制了组件。

使用轮播的组件

const ProjectList = props => {

  const [page, setPage] = useState(0);

  const projects = [
    <Project 
      name="Example"
      desc="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero nunc consequat interdum varius sit amet."
      image={require("../img/exampleproject.png")}
    />,
    <Project 
      name="Example2"
      desc="Another example. This one does nothing too. What a suprise!"
      image={require("../img/exampleproject.png")}
    />
  ]

  const genKey = () => {
    return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
  }

  const paginate = (newPage) => {
    setPage(newPage)
  }

  return (
    
    <div className="project-list">
      <AnimatePresence>
        <motion.button key={genKey()} onClick={() => paginate(page-1)}>
          <ArrowBackIosIcon/>
        </motion.button>
        <motion.div key={genKey()} className="project-list"
          initial={{opacity: 0}}
          animate={{opacity: 1}}
          exit={{opacity: 0}}
        >
          {projects[page]}
        </motion.div>
        <motion.button key={genKey()} onClick={() => paginate(page+1)}>
          <ArrowForwardIosIcon/>
        </motion.button>
      </AnimatePresence>
    </div>
  );

我不确定如何在片段编辑器中使用像 Framer Motion 这样的库,所以我把它放在了 CodeSandbox

编辑无价的sammet-9w1t3

当我不使用键时,它按预期工作,但是每当我单击其中一个箭头按钮时,它都会引发以下警告

警告

PS我知道最终页面值将超出长度的范围projects,我计划在我可以解决这个问题后修复它。

4

1 回答 1

2

实际上,您在这里不需要任何密钥。为 react 管理的元素添加键(以及添加随机键 - 就像您对Math.random()方法所做的那样)将覆盖 react 预定义的键,并可能导致您的程序在您到达此处时出现某种呈现错误。

仅当您从数组生成组件时才需要键(例如使用 map 函数)。

文档

键帮助 React 识别哪些项目已更改、添加或删除。应为数组内的元素提供键,以使元素具有稳定的身份

在这里你不需要那个。

此外,每次渲染的密钥都必须相同,在这里您生成一个随机密钥(每次渲染此组件时从数学随机方法)。

现在因为你使用这个库:https ://www.framer.com/api/motion/animate-presence/#usage

它精确地表明您必须使用密钥。这里的问题是你必须给出一个常量键。所以删除 Math Random 函数并给出一些常量字符串,就像我在这里所做的那样:

import React, { useState } from "react";
import Section from "./Section.js";
import { AnimatePresence, motion } from "framer-motion";
import Project from "./Project.js";
import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos";
import ArrowForwardIosIcon from "@material-ui/icons/ArrowForwardIos";

const ProjectList = props => {
  const [page, setPage] = useState(0);

  const projects = [
    <Project
      name="Example"
      desc="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero nunc consequat interdum varius sit amet."
      image={
        "https://i.picsum.photos/id/928/600/300.jpg?hmac=ai-33AKRXhJnTcm88ArxRypuNNrfztMdJ-ui_8dhe8c"
      }
    />,
    <Project
      name="Example2"
      desc="Another example. This one does nothing too. What a suprise!"
      image={
        "https://i.picsum.photos/id/258/600/300.jpg?hmac=d-pTq52drP8dj3vsxB72sOgifDUNcookREV33ffONbw"
      }
    />
  ];



  const paginate = newPage => {
    setPage(newPage);
  };

  return (
    <div className="project-list">
      <AnimatePresence>
        <motion.button key="img1" onClick={() => paginate(page - 1)}>
          <ArrowBackIosIcon />
        </motion.button>
        <motion.div
          key="img2"
          className="project-list"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
        >
          {projects[page]}
        </motion.div>
        <motion.button key="img3" onClick={() => paginate(page + 1)}>
          <ArrowForwardIosIcon />
        </motion.button>
      </AnimatePresence>
    </div>
  );
};

export default ProjectList;


于 2020-08-01T20:17:14.130 回答