ReactJS: как отобразить коллекцию объектов

#reactjs

#reactjs

Вопрос:

Итак, я совсем новичок в веб-разработке последние пару дней. Я работаю на c и не могу разобраться во всех принципах reactjs. У меня есть 2 класса. Дочерний класс с именем JobAd должен отображать некоторую информацию, которую он получил из props.

 export default class JobAd extends Component {
    constructor(props) {
        super(props);
        this.state ={
            index: props.index,
            id: props.jobId,
            name: props.name,
            description: props.description,
            location: props.location,
            adress: props.adress,
            alreadyApplied: props.alreadyApplied,
            open: false,
           // toggleJob: props.toggleJob,
        };
        this.toggleJob = props.toggleJob;
    }
    
    render() {
        return (
            <div className={`${styles.jobAd} d-flex`   "job "   (this.state.open ? 'open': '')} key={this.state.index} onClick={() => this.toggleJob(this.state.index)}>
                <div className={`${styles.jobTitle}`}>
                   {this.state.location} - {this.state.name}  
                </div>
                <div className={`${styles.jobDetails}`}>
                    <div className={`${styles.jobDescription}`}> {this.state.description}</div>
                    <div className={`${styles.jobAdress}`}>{this.state.adress}</div>
                    <ApplyButton jobId= {this.props.id} alreadyApplied = {this.props.alreadyApplied}/>
                </div>
            </div>
        )
    }
}
  

Второй класс запрашивает базу данных MongoDB и создает объекты jobAd, заполняя их информацией, полученной из базы данных.

 class JobExplorer extends React.Component
{
...

result.data.jobs.forEach(job => {
              var find = job.employees.find(obj => obj === userId);

              if (!(find === undefined)) {
                alreadyApplied = true;
              }


              var toPush = new JobAd  ({
                index: i,
                id:job._id,
                description:job.description,
                name:job.name,
                location:job.locationName,
                adress:job.locationAdress,
                alreadyApplied:alreadyApplied,
                open:false,
                toggleJob: this.toggleJob.bind(this)
              });
              jobList2.push(toPush);
              console.log("look");
              console.log(jobList2) 
              });
             
            
            this.setState({
              jobList: jobList2
            })


            this.setState({
              error: null,
              jobs: result.data.jobs
            });
...

render()
      {
              console.log("look2");
        
        console.log(this.state.jobList);
        return (
          <div><Navigation /> 
                                        {this.state.jobList}
          </div>
          );
      }

  

Но я столкнулся со следующей ошибкой, для которой я не могу найти исправление.

Ошибка: Объекты недопустимы как дочерние элементы React (найдено: объект с ключами {props, context, refs, updater, state, toggleJob}). Если вы хотели отобразить коллекцию дочерних элементов, используйте вместо этого массив.

Как я должен создавать экземпляры этих объектов, чтобы я мог отображать их, используя «архитектуру», которую я написал. Есть ли фундаментальный недостаток в моих классах?

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

1. Возможно, вам захочется обратиться к документации react, чтобы узнать, как отображать списки, см.: React — Lists

Ответ №1:

Приведенный ниже фрагмент не работает, потому что new вернет object (this) не компонент react.

Итак, вместо

 var toPush = new JobAd({
    index: i,
    id: job._id,
    ...
});
jobList2.push(toPush); 
  

вы можете сделать это

 var toPush = <JobAd
    index={i}
    id={job._id}
    ...
/>;
  

Приведенный выше фрагмент работает, потому что <JobAd ... /> преобразуется в React.createElement(JobAd, ... ) . Тем не менее, вы все равно не должны делать это так. поскольку есть много лучших способов сделать это. одним из них является:

сохраните только данные в joblist , а затем отобразите список данных в JobAd компоненте

как показано ниже:-

 render(){
    return this.state.joblist.map((job, i) => (
        <JobAd
            key={job._id}
            index={i}
            ...
        />
    ));
}
  

Ключ — это действительно важная вещь. Читайте об этом:https://reactjs.org/docs/lists-and-keys.html

Вещи, которые можно было бы улучшить:-

  1. Не копируйте реквизиты в состоянии, как вы делаете в JobAd классе, вместо этого непосредственно визуализируйте реквизиты.

  2. Не вызывайте setState дважды, как в JobExplorer . вы могли бы установить все ключи в setState одновременно. поскольку это привело бы к отображению компонента дважды.

Предложения:-

  1. Вам следует избегать использования var , поскольку это может вызвать некоторые проблемы здесь.
  2. поскольку вы только начинающий, попробуйте сначала использовать функциональный компонент. их гораздо проще понять

Ответ №2:

Похоже, у вас неправильное представление о состоянии / реквизитах в React и веб-разработке. Это очень нормально; сначала я изучил python и Java, и многие учебные пособия, похоже, предполагают, что люди просто уже знают это.

«Состояние» в общем случае относится к переменным, содержащим / ссылающимся на значения, которые могут изменяться без обновления страницы в вашем приложении. Если вы знаете, что значение не изменится, его не нужно сохранять в состоянии. Сохранение ее в обычной переменной — это именно то, что вы должны сделать.

«Реквизит» — это просто другое слово для аргументов, которые передаются компонентам React. На самом деле это еще не все, но, как новичку, это все, что вам нужно знать на данный момент.

Итак, в вашем job add такие вещи, как имя, адрес, задания, описание, не должны переходить в состояние, потому что они не изменятся в результате взаимодействия с пользователем или по любой другой причине, если не изменятся базовые данные, из которых они загружены, но тогда это будет обрабатываться не React, а API, из которого ваше приложение получает данные. Они должны просто отображаться, поэтому обращайтесь к ним следующим образом.props.address в вашем методе рендеринга. Значение для open, однако, должно быть в состоянии, потому что это определенно может измениться.

Что касается ошибки, похоже, вы неправильно вызываете JobAd. Вам нужно использовать синтаксис <Job Ad/> , а не new JobAd …это не будет работать в React.

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