【问题标题】:How to get a particular property of one JSON using one common property with other JSON objects?如何使用与其他 JSON 对象的一个​​公共属性来获取一个 JSON 的特定属性?
【发布时间】:2019-03-01 11:30:21
【问题描述】:

我是 react.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)} />
   ) 
}

【问题讨论】:

  • 您从控制台返回的错误是什么?

标签: javascript reactjs ecmascript-6 lodash ecmascript-2017


【解决方案1】:

在我看来,当第一次渲染发生时,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 或其他组件的构造函数中)。渲染方法 应该是 props 和 state 的纯函数;构造函数的副作用是一种反模式, 但可以移动到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)} />
   );
}

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

这样,每次调用组件实例的render 方法时,都会传递对就地声明的匿名函数的引用。然后,当用户决定单击时,将在某个不可预测的时间点调用此函数,即调度类型为“click”的 MouseEvent。

选项 2:让 this.wikiLink(•) 返回一个函数!

函数返回函数的概念通常被称为部分应用,或者在与此类似的情况下更常见的是闭包。所以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 预计会接收到一个函数,所以我们解决了类型匹配的问题。因为我们用一些参数TEAM_NAME 调用wikiLink,并且每次执行该函数时都会应用这个参数,所以我们解决了保留上下文的问题。这不是很棒吗!


要更好地了解如何使用返回函数的函数,请查看this Codesandbox,第 16 到 23 行。希望它能让您了解如何在需要管理 React 状态的情况下利用闭包组件。

干杯!

【讨论】:

  • 嗨,这真的很有帮助。它解决了这个问题。非常感谢
【解决方案2】:

函数wikiLink 不是类函数,也没有绑定到您的组件。您可以使用 es6 语法来绑定 wikiLink,也可以将 wikiLink 绑定到您的组件。

要么制作wikiLink 之类的东西

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

或者: 在您的 constructor 中,您会执行类似的操作

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

【讨论】:

  • 为什么分配wikiLink = (TEAM_NAME) 有意义?
  • 我们没有将TEAM_NAME 分配给wikiLink。这只是定义函数的另一种方式。 TEAM_NAME 仍然是传递给 wikiLink 函数的参数
  • 有道理
【解决方案3】:

在您的 wikiLink 中,您似乎正在尝试使用 =&gt; 箭头函数快捷方式?

您的 wikiLink 函数中缺少某些内容。你要么做类似的事情

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

或上面的答案所说的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 2022-08-17
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    相关资源
    最近更新 更多