React Ref: функция Ref для массива объектов регистрирует только 1-й элемент

Я сопоставил массив объектов из внешнего API, который успешно отображает их содержимое. Теперь я пытаюсь получить доступ к их отдельным clientHeights через React ref, но, похоже, он выводит ТОЛЬКО первый элемент, когда я вхожу в свою консоль:


class ImageList extends React.Component{
  constructor(props){
    super(props)

    this.imageRef = React.createRef()
    
  }
  

  componentDidMount(){
    console.info(this.imageRef)
  }
  
  
  render(){

    
    const images= this.props.images.map((image)=>{
      
      return( 
          <img ref = {this.imageRef}
               key = {image.id} 
               src = {image.urls.regular}
               alt = {image.description} />
      )})
      
      
      return(
        <div  className = "image-list" >
          {images}
        </div>
      
    )
    
  }
  
  
}

Я пытаюсь получить все их clientHeights, а не только первый. Спасибо

Свойство или переменная может содержать только одно значение, поэтому this.imageRef может содержать ссылку только на один из элементов. Вам нужно создать ссылку для каждого изображения.

Felix Kling 17.12.2020 14:52

Даже если мои элементы отображаются? ref = {this.imageRef} key = {image.id} src = {image.urls.regular} alt = {image.description} . key, src и alt сопоставляются и создают разные значения для каждого отображаемого элемента, так почему Ref отличается

Chijindu 17.12.2020 15:31

key, src и alt — все значения, которые вы передаете компоненту. Хотя вы также передаете что-то компоненту с помощью ref, компонент в конечном итоге назначает ему ссылку на свой базовый элемент DOM. Это означает, что у вас есть компоненты изображения X, которые пытаются присвоить свой элемент DOM одной и той же ссылке. Это не может работать.

Felix Kling 17.12.2020 15:36
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
375
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваш код назначит каждому узлу img значение this.imageRef. Я не уверен, почему он сохраняет первую ссылку, но в любом случае он не будет работать так, как вы ожидаете. Чтобы получить массив узлов img, вам нужно, чтобы ссылка была массивом и добавляла в него каждый узел. ref prop может быть функцией, поэтому попробуйте что-то вроде этого

class ImageList extends React.Component{
  constructor(props){
    super(props)
  }
  

  componentDidMount(){
    console.info(this.imageRefs)
  }
  
  
  render(){
    this.imageRefs = []
    
    const images= this.props.images.map((image)=>{
      
      return( 
          <img ref = {ref => {this.imageRefs.push(ref)}}
               key = {image.id} 
               src = {image.urls.regular}
               alt = {image.description} />
      )})
      
      
      return(
        <div  className = "image-list" >
          {images}
        </div>
      
    )
    
  }
  
  
}

Вау, это сработало. Пожалуйста, если это не слишком беспокоит, можете ли вы объяснить, как ваш код работал без инициализации React.createRef()? Также не могли бы вы объяснить эту строку кода ref = {ref => {this.imageRefs.push(ref)}. Я не понимаю, почему вставляемая ссылка имеет значения, она была ПРОСТО определена только внутри функции. Или это нормальный синтаксис? Я впервые использую Refs, и я извиняюсь за кучу вопросов, спасибо. Кроме того, мой исходный код полностью работал в этом уроке, который я смотрю, поэтому я понятия не имею, что не так.

Chijindu 17.12.2020 15:27

@Chijindu: см. reactjs.org/docs/refs-and-the-dom.html#callback-refs

Felix Kling 17.12.2020 15:34
React.createRef() нужен, если вы хотите, чтобы волшебное ref = {this.imageRef} сработало. Во времена до React.createRef() мы также использовали простые свойства для хранения ссылок, но тогда они были бы null при первом рендеринге, потому что узлы DOM впервые создаются только в конце первого рендеринга. Это вызвало много проблем у разработчиков, поэтому команда React придумала React.createRef(). По сути, он создает объект-оболочку, который всегда существует и имеет свойство current, которое может быть null или ссылкой на узел DOM, но, по крайней мере, само свойство компонента никогда не бывает null.
Miloš Rašić 18.12.2020 12:04

Поддерживая массив ссылок на узлы DOM, вы сами делаете то, что сделал бы React.createRef(), но используете массив вместо объекта-оболочки, чтобы вы могли хранить ссылки на несколько узлов DOM.

Miloš Rašić 18.12.2020 12:05

Другой способ, который я получил (полученный из учебника), - это отобразить изображение и его содержимое как ДРУГОЙ компонент (назовите его ImageCard, где я сейчас поместил ссылку), а затем отобразить этот компонент вместо исходного тега <img/> следующим образом:

class ImageList extends React.Component{

  

  
  
  render(){
    
    
    const images= this.props.images.map((image)=>{
      
      return( 
          <ImageCard key = {image.id} image= {image}/>
      )})
      
      console.info(images);
      return(
        <div  className = "image-list" >
          {images}
        </div>
      
    )
 
  }
  
  
}

Это позволяет отображать любые манипуляции с компонентом ImageCard. Я понял это только сейчас, после повторного просмотра, кстати

Другие вопросы по теме