Как получить конкретное свойство одного JSON, используя одно общее свойство с другими объектами JSON? - PullRequest
0 голосов
/ 25 сентября 2018

Я новичок в реагировании на проблемы.js и сталкиваюсь с проблемами при выполнении следующей задачи.

При запуске по коду он показывает, что setState не может быть использован, и приложение разрывается.У меня есть эти два объекта, obj2 генерирует таблицу 3 columns.Мне нужно сделать каждую ячейку столбца definition, на которую нельзя щелкать null, что приводит меня к ссылке team_wiki, которая присутствует в obj1.

obj1: {
    providers : [
         {team_name : "XYZ", team_wiki : "https://example.com", team_id : 1},
         {team_name : "ABC", team_wiki : "null", team_id : 2},
         {team_name : "LMN", team_wiki : "https://example2.com", team_id : 3},
         {team_name : "MNO", team_wiki : "https://example3.com", team_id : 4}
    ]
}

obj2: {
    products : [
       {team_name : "XYZ", definition : "this team handles XYZ products", metric_id : 101},
       {team_name : "ABC", definition : "this team handles ABC products", metric_id : 201},
       {team_name : "LMN", definition : "this team handles LMN products", metric_id : 301},
       {team_name : "MNO", definition : "this team handles MNO products", metric_id : 401}
    ]
}

Код:

state = {
    API_DATA : {},
    TEAM_WIKI : ''
}

componentDidMount(){
   // fetch the obj1 data and sets it to the state called API_DATA
}

wikiLink = (TEAM_NAME) {
   // getting TEAM_NAME from a component inside the render method
   const wiki = this.state.API_DATA.map(provider => {
       if (provider.team_name = TEAM_NAME && provider.team_wiki !== null) {
           return provider.team_wiki
       }
   })
   .map(link => {
       if (link !== undefined) {
           return link
       }
   })

   this.setState({
      // TEAM_WIKI is a state { its a string } where i want to store the 
      //team_wiki at last
      TEAM_WIKI : wiki
   })
}

render() {

   return (
         // i want to use it something like this
        < href="this.state.TEAM_WIKI" onClick={this.wikiLink(TEAM_NAME)} />
   ) 
}

Ответы [ 3 ]

0 голосов
/ 25 сентября 2018

В вашей wikiLink похоже, что вы пытаетесь использовать ярлык функции стрелки =>?

Вам не хватает чего-то в вашей функции wikiLink.вы либо делаете что-то вроде

function wikilink (Data) {//rest of your code}

или что сказал ответ выше.

0 голосов
/ 26 сентября 2018

Мне кажется, что когда происходит первый в истории рендеринг, this.wikiLink называется , который называется , а не передается как ссылка .Почему я так думаю?Потому что я вижу круглые скобки там.Тело этого метода содержит вызов this.setState, что означает, что состояние компонента изменяется во время рендеринга, и это является нарушением жизненного цикла компонента.

Рассмотрим случай:

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      buttonClicked: false,
    };
    this.handleClickButton = this.handleClickButton.bind(this);
  }

  handleClickButton() {
    this.setState({
      buttonClicked: true,
    });
  }

  render() {
    return (
      <button onClick={this.handleClickButton()}>click me</button>
    );
  }
}

Есть проблема!Выражение this.handleClickButton() является вызовом функции.Внутри него есть инструкция по изменению состояния.Когда код пытается это сделать, React отображает предупреждение:

Предупреждение: setState (...): невозможно обновить во время существующего перехода состояния (например, в render или в конструкторе другого компонента).).Методы рендеринга должны быть чистой функцией реквизита и состояния;побочные эффекты конструктора являются анти-паттернами, но их можно переместить в componentWillMount.

. Вместо этого мы действительно хотим вызвать функцию this.handleClickButton при нажатии кнопки.Для этого нам нужно передать ссылку на эту функцию в onClick реквизит, например:

  render() {
    return (
      <button onClick={this.handleClickButton}>click me</button>
    );
  }

обратите внимание на отсутствие круглых скобок.

Итак, что вы должны сделатьтогда?

Есть две опции:

Опция 1: анонимная функция внутри onClick

Вместо записи

render() {
   return (
     // i want to use it something like this
     <a href="this.state.TEAM_WIKI" onClick={this.wikiLink(TEAM_NAME)} />
   );
}

do

render() {
   return (
     // i want to use it something like this
     <a href="this.state.TEAM_WIKI" onClick={() => this.wikiLink(TEAM_NAME)} />
   );
}

Таким образом, ссылка на анонимную функцию, объявленную на месте, передается при каждом вызове render метода экземпляра компонента.Затем эта функция будет вызываться в какой-то непредсказуемый момент времени, когда пользователь решит щелкнуть, то есть отправить MouseEvent типа «click».

Вариант 2: сделать this.wikiLink (•) returnфункция!

Концепция функции, возвращающей функцию, часто упоминается как частичное применение или, в случаях, подобных этому, чаще всего, замыкание .Таким образом, функция wikiLink будет вместо этого:

wikiLink(TEAM_NAME) {
  // getting TEAM_NAME from a component inside the render method
  const wiki = this.state.API_DATA.map(provider => {
    if ((provider.team_name = TEAM_NAME && provider.team_wiki !== null)) {
      return provider.team_wiki;
    }
  }).map(link => {
    if (link !== undefined) {
      return link;
    }
  });

  this.setState({
    // TEAM_WIKI is a state { its a string } where i want to store the
    //team_wiki at last
    TEAM_WIKI: wiki
  });
}

выглядеть следующим образом:

wikiLink(TEAM_NAME) {
  return () => {
    // getting TEAM_NAME from a component inside the render method
    const wiki = this.state.API_DATA.map(provider => {
      if ((provider.team_name = TEAM_NAME && provider.team_wiki !== null)) {
        return provider.team_wiki;
      }
    }).map(link => {
      if (link !== undefined) {
        return link;
      }
    });

    this.setState({
      // TEAM_WIKI is a state { its a string } where i want to store the
      //team_wiki at last
      TEAM_WIKI: wiki
    });
  };
}

Так что при вызове она возвращает новую функцию.Поскольку ожидается, что onClick prop получит функцию, мы решаем проблему сопоставления типов.Поскольку мы вызываем wikiLink с некоторым аргументом TEAM_NAME и этот аргумент применяется каждый раз, когда выполняется эта функция, мы решаем проблему сохранения контекста.Разве это не круто!


Чтобы получить более полное представление об использовании функции, возвращающей функцию, посмотрите этот кодовый ящик , строки с 16 по 23. Надеюсь, это даст некоторыеидея о том, как использовать замыкания в ситуациях, когда вам нужно управлять состоянием компонента React.

Cheers!

0 голосов
/ 25 сентября 2018

Функция wikiLink не является функцией класса и не связана с вашим компонентом.Вы можете использовать синтаксис es6 для привязки wikiLink или связать wikiLink с вашим компонентом.

Либо сделать wikiLink что-то вроде

wikiLink = (TEAM_NAME) => { // rest of your code

ИЛИ: в вашем constructor вы делаетечто-то вроде

constructor(){
this.wikiLink = this.wikiLink.bind(this)
}
...