Сопоставление данных из массива в дочернем компоненте и родительском компоненте

#javascript #arrays #reactjs

#javascript #массивы #reactjs

Вопрос:

У меня есть данные, хранящиеся в data.js файл в массиве. Я показываю эти данные в дочернем компоненте (только первый объект в массиве). Я хочу отобразить через тот же массив в родительском компоненте (путем рендеринга <ChildComponent> ). Как я могу это сделать?

data.js

 export default {
  accordionItems: [
    {
      id: 1,
      title: 'Why is my car not green?',
      answer: 'We ran out of green color',
    },
    {
      id: 2,
      title: 'Where have all the drivers gone?',
      answer: 'It's lunch time',
    },
    {
      id: 3,
      title: 'Do you have a book of complains',
      answer: 'You can write at info@mail.eu',
    },
  ],
};
  

дочерний компонент

 import Data from './data';

class AccordionItem extends Component {
  constructor(props) {
    super(props);
    this.state = {
      question: Data.accordionItems[0], //if I remove [0], no data is rendered
    };
  }

 return (
    <div >
      <div>
        <p>{question.title}</p>
        <button>toggle</button>
      </div>
      <p>{question.answer}</p>
      <hr />
    </div>
 );
  

Родительский компонент

 import AccordionItem from './AccordionItem';
import Data from './data';


class Accordion extends Component {
  constructor(props) {
    super(props);
    this.state = {
      accordionItems: Data.accordionItems,
    };
  }
render() {
    const { accordionItems } = this.state;
    return accordionItems.map(accordionItem => (
      <AccordionItem key={accordionItem.id} />
  

Я хочу получить все 3 объекта из массива «данные» в родительском компоненте, теперь я получаю 3 одинаковых компонента только с первым объектом.

Ответ №1:

Передайте элемент в качестве реквизита:

  <AccordionItem question={accordionItem} ... />
  

Вы можете получить к нему доступ с помощью метода render():

 render() {
 const { question } = this.props;

 return (
   <div >
     <div>
       <p>{question.title}</p>
       <button>toggle</button>
     </div>
     <p>{question.answer}</p>
   </div>
 );
}
  

Вы не должны использовать состояние вообще (пока).

Ответ №2:

Вы можете просто передать данные из самой функции map следующим образом:

 accordionItems.map(accordionItem => (
      <AccordionItem
        key={accordionItem.id}
        open={[`isOpen-${accordionItems.id}`]}
        data={accordionItem}
      />
));
  

И в дочернем:

 class AccordionItem extends Component {
  constructor(props) {
    super(props);
    this.state = {
      question: props.data, //data from map function in parent
    };
  }
  

Комментарии:

1. Похоже, это работает для родительского компонента. но дочерний компонент выдает ошибку: не удается прочитать свойство ‘title’ неопределенного

2. В одном элементе мне нужно было передать индекс массива. <AccordionItem data={Data.accordionItems[0]} Все в порядке.

3. Вот наилучшее возможное решение , на мой взгляд : codesandbox.io/s/y2lrywpk21

Ответ №3:

Возможно, вам следует прочитать немного больше о компонентах и передаче реквизитов в React.

Что вы могли бы сделать, чтобы это сработало, так это вместо импорта Data в ваш AccordionItem компонент передать его в AccordionItem через props.

Это выглядело бы примерно так:

 import AccordionItem from './AccordionItem';
import Data from './data';


class Accordion extends Component {
  constructor(props) {
    super(props);
    this.state = {
      accordionItems: Data.accordionItems,
    };
  }

  render() {
    const { accordionItems } = this.state;
    return accordionItems.map(accordionItem => (
        <AccordionItem
          key={accordionItem.id}
          item={accordionItem}
          open={[`isOpen-${accordionItems.id}`]}
        />
    ))
  }
  

Теперь элемент должен стать доступным через реквизиты в дочернем компоненте:

  class AccordionItem extends Component {

   render(){
     const { question } = this.props
     return (
       <div >
         <div>
           <p>{question.title}</p>
           <button>toggle</button>
         </div>
         <p>{question.answer}</p>
         <hr />
       </div>
     );
   }