Как установить состояние из сопоставленного элемента в компоненте React

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

Я пытался установить свойство (projectID) с помощью onClick, и хотя я могу заставить его переключать один элемент состояния (расширенный или нерасширенный), он делает это для ВСЕХ возвращаемых результатов. Поэтому я пытался получить идентификатор проекта (установленный в данных) и использовать его для установки условного выражения. Но я не могу заставить projectId обновляться одним щелчком мыши. Я кратко поиграл с контекстом, но я думаю, что мне не хватает чего-то более простого. Я пытался это сделать в onClick (как показано) и изнутри onViewChange, но это не сработало, так как я не могу получить доступ к item.id из-за пределов сопоставленного элемента.

Я использую условное выражение, основанное на реквизите, переданном от пары уровней выше, чтобы установить категорию, показывающую только те объекты, которые я хочу. Эта часть, кажется, работает. Поэтому я удалил свое расширенное состояние, так как здесь нет необходимости.

 import React from 'react';
 import projects from '../data/projects.json';

 class ProjectCard extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
        projects,
        expanded: false,
        projectId: -1
    }
  }

  onViewChange = (e) => {
    this.setState({
        expanded: !this.state.expanded
    });
    console.info(this.state.projectId)
  };

  render() {
    return (
        <React.Fragment>
        {this.state.projects.map((item) => {
            if (!this.state.expanded && item.category === this.props.category) { 
                return (
                        <div key = {item.id} className = "project-card">
                            <div className = "previewImg" style = {{backgroundImage: `url(${item.previewImg}` }} ></div>
                            <div className = "copy">
                                <h2>{item.title}</h2>
                                <p>{item.quickDesc}</p>
                            </div>
                            <div className = "footer">
                            {item.tools.map((tool) => {
                                return ( 
                                    <div key = {tool} className = "tools" style = {{backgroundImage: `url(${tool}` }}></div>
                                );
                            }
                            )}
                                <button onClick = {() => this.onViewChange({projectId: item.id})} className = "btn float-right"><i className = "fas fa-play"></i></button>
                            </div>
                        </div> 
                        );
                    }
            }

        )}
        </React.Fragment>
    );
  };
};

 export default ProjectCard;

Я установил консольный журнал, чтобы сообщать мне, изменяется ли projectId, и он всегда возвращается как мое значение по умолчанию (-1). Вставленная версия - единственная, которая не выдает ошибок в отношении неопределенных значений/объектов, но по-прежнему никаких изменений. Если я смогу заставить проект измениться на основе item.id с помощью нажатой кнопки, я думаю, что смогу понять условное выражение и взять его оттуда.

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

Ответы 1

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

На самом деле вы не устанавливаете состояние с новым projectId в обработчике кликов. Первый шаг — просто передать идентификатор элемента обработчику кликов, а не объекту:

onClick = {() => this.onViewChange(item.id)}

И вторая часть заключается в том, чтобы фактически использовать этот аргумент в вашем обработчике кликов:

onViewChange = (id) => {
    this.setState({
        expanded: !this.state.expanded,
        projectId: id
    });
 };

Кроме того, setState() является асинхронным, поэтому вы не можете делать то, что делали, и console.info свое состояние на следующей строке и ожидать, что оно изменилось. Зарегистрируйте состояние в верхней части вашей функции рендеринга, чтобы увидеть, когда оно изменится (после изменения состояния/реквизитов вызывается рендеринг). Или другой вариант — использовать необязательный второй аргумент setState, который представляет собой обратный вызов, выполняемый с новым состоянием:

this.setState({id: 5}, () => console.info(this.state.id)) <-- id will be 5

Это сработало отлично, спасибо! Я помню, как пробовал this.onViewChange(item.id) - и десятки других догадок "что, если я сделаю это", но я думаю, что упустил ту часть, где id передается обратно в onViewChange вместо передачи события. 60 часов обучающих видео, и это первый неучебник, который я пытаюсь пройти. Я очень ценю помощь!

cebronix 31.05.2019 16:55

@cebronix не беспокойтесь :) кстати, если вы тоже хотите пройти мероприятие, вы можете поставить лайк: onClick = {(event) => someFunction(event, ...otherArgs)}

Jayce444 01.06.2019 01:46

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