简体   繁体   English

在 map 循环中生成多个参考

[英]Generate multiple refs in map loop

I am still confused if I use useRef([]);如果我使用useRef([]);我仍然感到困惑the right way, as itemsRef returns Object {current: Array[0]} .正确的方法,因为itemsRef返回Object {current: Array[0]} Here in action: https://codesandbox.io/s/zealous-platform-95qim?file=/src/App.js:0-1157在这里行动: https://codesandbox.io/s/zealous-platform-95qim?file=/src/App.js:0-1157

import React, { useRef } from "react";
import "./styles.css";

export default function App() {
  const items = [
    {
      id: "asdf2",
      city: "Berlin",
      condition: [
        {
          id: "AF8Qgpj",
          weather: "Sun",
          activity: "Outside"
        }
      ]
    },
    {
      id: "zfsfj",
      city: "London",
      condition: [
        {
          id: "zR8Qgpj",
          weather: "Rain",
          activity: "Inside"
        }
      ]
    }
  ];

  const itemsRef = useRef([]);

  // Object {current: Array[0]}
  // Why? Isn't it supposed to be filled with my refs (condition.id)
  console.log(itemsRef);

  return (
    <>
      {items.map(cities => (
        <div key={cities.id}>
          <b>{cities.city}</b>
          <br />
          {cities.condition.map(condition => (
            <div
              key={condition.id}
              ref={el => (itemsRef.current[condition.id] = el)}
            >
              Weather: {condition.weather}
              <br />
              Activity: {condition.activity}
            </div>
          ))}
          <br />
          <br />
        </div>
      ))}
    </>
  );
}

In the original example I receive // Object {current: Array[3]} when I console.log(itemsRef);在原始示例中,当我console.log(itemsRef);时收到// Object {current: Array[3]} The difference is that I used in my version itemsRef.current[condition.id] as its a nested map loop and therefore i doesn't work.不同之处在于我在我的版本itemsRef.current[condition.id]中使用它作为嵌套的 map 循环,因此i不起作用。

import React, { useRef } from "react";
import "./styles.css";

export default function App() {
  const items = ["sun", "flower", "house"];
  const itemsRef = useRef([]);

  // Object {current: Array[3]}
  console.log(itemsRef);

  return items.map((item, i) => (
    <div key={i} ref={el => (itemsRef.current[i] = el)}>
      {item}
    </div>
  ));
}

You're using non-numeric string keys when adding the refs to itemRefs , which means they end up being properties of the array object, but not array elements , so its length remains 0 .在将refs添加到itemRefs时,您使用的是非数字字符串键,这意味着它们最终成为数组 object 的属性,但不是数组元素,因此它的长度保持0 Depending on your console, it may or may not show non-element properties on an array object.根据您的控制台,它可能会或可能不会在数组 object 上显示非元素属性。

You could make them array elements instead by using the index from map (but keep reading:):您可以使用map中的index将它们设为数组元素(但请继续阅读:):

{cities.condition.map((condition, index) => (
    <div
        key={condition.id}
        ref={el => (itemsRef.current[index] = el)}
    >
        Weather: {condition.weather}
        <br />
        Activity: {condition.activity}
    </div>
))}

but depending on what you're doing with those refs I would avoid that in favor of making each condition its own component instead:但是根据您对这些参考的处理方式,我会避免这种情况,而是将每个condition作为其自己的组件:

const Condition = ({weather, activity}) => {
    const itemRef = useRef(null);
  
    return (
        <div
            ref={itemRef}
        >
            Weather: {weather}
            <br />
            Activity: {activity}
        </div>
    );
};

Then get rid of itemRefs and do:然后摆脱itemRefs并执行以下操作:

{cities.condition.map(({id, weather, activity}) => (
    <Condition key={id} weather={weather} activity={activity} />
))}

One problem with your current way even if we use array elements is that itemRefs will continue to have three elements in it even when the DOM elements that they used to refer to are gone (they'll have null instead), since React calls your ref callback with null when the element is removed, and your code is just storing that null in the array.即使我们使用数组元素,您当前方式的一个问题是itemRefs将继续在其中包含三个元素,即使它们过去引用的 DOM 元素已经消失(它们将具有null代替),因为 React 调用您的ref删除元素时使用null回调,并且您的代码只是将该null存储在数组中。

Alternatively, you might use an object:或者,您可以使用 object:

const itemRefs = useRef({});
// ...
{cities.condition.map(condition => (
    <div
        key={condition.id}
        ref={el => {
            if (el) {
                itemsRef.current[condition.id] = el;
            } else {
                delete itemsRef.current[condition.id];
            }
        }}
    >
        Weather: {condition.weather}
        <br />
        Activity: {condition.activity}
    </div>
))}

Or perhaps a Map :或者也许是Map

const itemRefs = useRef(new Map());
// ...
{cities.condition.map(condition => (
    <div
        key={condition.id}
        ref={el => {
            if (el) {
                itemsRef.current.set(condition.id, el);
            } else {
                itemsRef.current.delete(condition.id);
            }
        }}
    >
        Weather: {condition.weather}
        <br />
        Activity: {condition.activity}
    </div>
))}

But again, I'd lean toward making a Condition component that manages its own ref.但同样,我倾向于制作一个Condition组件来管理它自己的 ref。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM