Компонент прародителя не передает аргумент в функцию

У меня есть некоторые сомнения, пытаясь понять, как реакция работает с функциями в качестве реквизита, передавая их дочерним компонентам. Я уже видел несколько руководств, но на данный момент не понял свою проблему.

По сути, у меня есть простой компонент, который передает список вниз, и другой компонент, который обрабатывает список с помощью Array.map для отображения другого компонента.

В основном у меня есть следующее:

App.js -> Цитаты -> Цитата.

И я хочу обработать щелчок по компоненту Quote. Поэтому каждый раз, когда пользователь нажимает Quote, я хочу обрабатывать его в APP.js.

Я уже пытался передать ссылку в качестве опоры и в компоненте кавычек app.js для вызова функции, но это не сработало.

Это то, что я пробовал до сих пор:

App.js

import React, { Component } from 'react';
import classes from './App.module.css';

import Quotes from '../components/quotes/quotes'

class App extends Component {
  state = {
    quotes: [
      { id: 1, text: "Hello There 1" },
      { id: 2, text: "Hello There 2" },
      { id: 3, text: "Hello There 3" },
      { id: 4, text: "Hello There 4" }
    ],
    clickedQuote: "none"
  }

  handleClickedQuote (id) {
    console.info(id)
    const quoteIndex = this.state.quotes.findIndex(q => q.id === id)

    this.setState({
      clickedQuote: this.state.quotes[quoteIndex].text
    })
  }

  render() {
    return (
      <div className = "App">
        <div className = {classes['quotes-wrapper']}>
          <Quotes clicked = {this.handleClickedQuote} quotes = {this.state.quotes}/>
          <p>clicked quote {this.state.clickedQuote}</p>
        </div>
      </div>
    );
  }
}

export default App;

Цитаты.js

import React from 'react';
import Quote from './quote/quote'

const quotes = (props) => props.quotes.map((quote) => {
  return (
    <Quote clicked = {props.clicked} text = {quote.text}/>
  )
})

export default quotes

Цитата.js

import React from 'react';
import classes from './quote.module.css'

const quote = (props) => {
  return (
    <div onClick = {() => props.clicked(props.id)} className = {classes.quote}>
      <p className = {classes['quote-text']}>{props.text}</p>
    </div>
  )
}

export default quote

Мне нужно получить идентификатор hanleClickedQuote в функции App.js. Что я делаю неправильно?

console.info(id) работает?\

Maheer Ali 07.04.2019 21:33
Поведение ключевого слова "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) для оценки ваших знаний,...
1
1
45
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно явно передать идентификатор в качестве реквизита. Итак, в Quotes.js в вашем map(), что-то типа:

<Quote id = {quote.id} clicked = {props.clicked} text = {quote.text}/>

Обновление: как сказал @Ashkan в своем ответе, вам также необходимо правильно связать свой обработчик.

не думаю, что это главная проблема

Ashkan Pourghasem 07.04.2019 21:54

Я думаю, что это основная/самая очевидная проблема. Если они правильно свяжут свою функцию, как вы предложили, код все равно не будет делать то, что они хотят.

Colin Ricardo 07.04.2019 21:57

То же самое касается другой проблемы. Даже если вы передадите реквизит, код выдаст исключение, поскольку this.state не определено. Просто пытаюсь направить его по правильному пути, поскольку, исходя из опыта, многие люди сталкиваются с этой проблемой, когда начинают использовать React. Как вы сказали, эта ошибка немного более очевидна и ее легче отладить, чем проблему, которая требует, чтобы вы знали, почему «это» получает неправильное значение.

Ashkan Pourghasem 07.04.2019 21:59

Конечно, и то, и другое вместе полезнее.

Colin Ricardo 07.04.2019 22:11
Ответ принят как подходящий

Ну, в вашем коде есть две вещи, которые идут очень неправильно. Первая — распространенная проблема в сообществе JS. Я предлагаю вам подробнее изучить использование ключевого слова this. в App.js вы определяете свой метод как объявление функции.

handleClickedQuote(id) {
    console.info(id)
    const quoteIndex = this.state.quotes.findIndex(q => q.id === id)

    this.setState({
        clickedQuote: this.state.quotes[quoteIndex].text
    })
}

Теперь ключевое слово «this» в объявлениях функций устанавливается динамически, что означает, что здесь «this» фактически устанавливается при вызове функции, и, поскольку это обработчик событий, значение «this» на самом деле будет вашим событием! Вы можете проверить это. Но мы хотим, чтобы «это» относилось к нашему классу, чтобы мы могли получить доступ к состоянию.

Есть два способа исправить это, первый:

Вы можете привязать правильное значение для this в конструкторе вашего класса App.js следующим образом (по-старому):

constructor(props) {
    super(props);
    this.handleClickedQuote = this.handleClickedQuote.bind(this);
}

Это заменяет метод в вашем классе версией, которая использует правильное значение this на этапе построения вашего объекта.

Или, что еще проще, вы можете использовать стрелочную функцию, так как ключевое слово this в стрелочной функции задается лексически:

handleClickedQuote = id => {
    console.info(id);
    const quoteIndex = this.state.quotes.findIndex(q => q.id === id);

    this.setState({
        clickedQuote: this.state.quotes[quoteIndex].text
    });
}

ПРИМЕЧАНИЕ. В стрелочной функции значение this в основном относится ко всему, что находится за пределами этого блока кода, который в данном случае является всем вашим объектом.

Также у вас есть небольшая ошибка в вашем коде, о которой кто-то упомянул. На самом деле вы забыли передать идентификатор цитаты в качестве реквизита компоненту Quote. Но это всего лишь небольшая оплошность. Важно знать, что эта проблема связана не столько с React, сколько с самим JS. Мой совет — немного углубиться в JS и изучить все тонкости и технические особенности языка. Это избавит вас от многих хлопот в будущем. Также поработайте над своими навыками отладки, чтобы такие ошибки, как отсутствующая опора, не пропадали так легко.

Удачи

Я как бы знал о первом ответе, который вы мне дали, просто забыл об этом и подумал, что проблема не в этом. Просто быстрый вопрос, когда я передаю функцию, которая обрабатывается в компоненте с отслеживанием состояния, как указано выше, в дочерний компонент. Я должен использовать что-то вроде () => function(), когда я запускаю функцию, как в цитате, верно?

Filipe Costa 07.04.2019 22:39

@FilipeCosta Я не думаю, что в этом есть какие-то недостатки. Альтернативой может быть повторное использование привязки, только на этот раз вы привязываете параметры вместо переменной this. Лично я предпочитаю функцию стрелки, как и вы, если только вы не используете ES6 и не поддерживаете ее.

Ashkan Pourghasem 07.04.2019 22:44

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