React-spring: 'Two children with same key' when using useTransition

Created on 25 Mar 2019  Â·  1Comment  Â·  Source: pmndrs/react-spring

Hi, I'm new to react-spring. I'm getting a same-key error which I'm sure must be my fault.

Here's my component's code:

import React, { useState } from "react";
import { useTransition, animated } from "react-spring";
import useInterval from "../../hooks/useInterval";

const WordSlider = ({ children }) => {
  const [count, setCount] = useState(React.Children.count(children));
  const [currentIndex, setCurrentIndex] = useState(0);

  const transitions = useTransition(children, currentIndex, {
    initial: null,
    from: { opacity: 0, y: -100 },
    enter: { opacity: 1, y: 0 },
    leave: { opacity: 0, y: 100 }
  });

  useInterval(() => {
    setCurrentIndex((currentIndex + 1) % count);
  }, 2500);

  return (
    <p className="wordslider-container">
      {transitions.map(({ item, key, props }) => (
        <animated.span
          key={key}
          style={{
            position: "absolute",
            transform: props["y"].interpolate(y => `translate3d(0, ${y}%, 0)`),
            opacity: props["opacity"]
          }}
        >
          {children[currentIndex]}
        </animated.span>
      ))}
    </p>
  );
};

export default WordSlider;

and this is the actual error:

Warning: Encountered two children with the same key, `8`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.

But I'm not sure what am I doing wrong to cause the warning here, would really appreciate some help. Thanks!

question

Most helpful comment

It is most likely the second argument: useTransition(children, currentIndex,

it should be either an array of keys or a key accessor function. if you have an array of objects, say

const objects = [
  { guid: 1, content: "hello" },
  { guid: 2, content: "what's" },
  { guid: 3, content: "up" },
]

Then useTransition will be

useTransition(objects, object => object.guid, ...)

Now transition can recognize the items you're giving it, and detect changes amongst them.

Sometime the itemself itself is the key (it's an atomic string, bool, or number), in that case you can use null:

useTransition(show, null, ...)

The keys are used down there in the view, this is how it can retain an old state, even if the global or local state has changed. Now views can safely transition out.

>All comments

It is most likely the second argument: useTransition(children, currentIndex,

it should be either an array of keys or a key accessor function. if you have an array of objects, say

const objects = [
  { guid: 1, content: "hello" },
  { guid: 2, content: "what's" },
  { guid: 3, content: "up" },
]

Then useTransition will be

useTransition(objects, object => object.guid, ...)

Now transition can recognize the items you're giving it, and detect changes amongst them.

Sometime the itemself itself is the key (it's an atomic string, bool, or number), in that case you can use null:

useTransition(show, null, ...)

The keys are used down there in the view, this is how it can retain an old state, even if the global or local state has changed. Now views can safely transition out.

Was this page helpful?
0 / 5 - 0 ratings