如何获取通过地图功能生成的列表项的键?

时间:2018-06-23 03:54:32

标签: javascript reactjs

所以我正在学习React,我试图在stackoverflow和React自己的文档中寻找解决问题的方法,但是我仍然很困惑。

从本质上来说,我有一个10个子索引的列表,这些列表以subredditsArray变量的形式映射到列表项。

我呈现结果,并在将列表项单击到我的getSubredditInfo函数时尝试将选定的项传递。但是,这不起作用-event.target.key未定义。 (为澄清起见,我希望获取单击的单个列表元素的键。)

当我尝试仅获取event.target时,我得到了实际的htmlElement(例如:<li>Dota2</li>),在这里我想获取密钥,或者至少将此值转换为字符串而不用标签。我还尝试将onClick方法放在map函数的list标记中,但这没用。

以下是相关代码:

//this is where I get my data
componentDidMount(){
    fetch('https://www.reddit.com/api/search_reddit_names.json?query=dota2')
    .then(results => {
        return results.json();
    })
    .then(redditNames => {
        //this is there I set my subreddits state variable to the array of strings
        this.setState({subreddits: redditNames.names});
    })
}

   getSubredditInfo(event){
    //console.log(event.target.key); <-- DOESNT WORK

}

render() {

 var subredditsArray = this.state.subreddits.map(function(subreddit){
    return (<li key={subreddit.toString()}>{subreddit}</li>);
});

  return (
    <div className="redditResults">
      <h1>Top 10 subreddits for that topic</h1>
      <ul onClick={this.getSubredditInfo}>{subredditsArray}</ul>
    </div>
  );
}

我的问题基本上可以归结为:

  1. 如何从列表对象中获取键值?
  2. 此外,还有比我目前更好的方法来生成列表吗?

谢谢。

编辑:添加了我的componentDidMount函数,希望它能使您更多地了解。

4 个答案:

答案 0 :(得分:1)

尝试以下代码:

class App extends React.Component {
  constructor(props){
     super(props);
     this.state = {subreddits:[]};
  }
  
  componentDidMount(){
    fetch('https://www.reddit.com/api/search_reddit_names.json?query=dota2')
    .then(results => {
        return results.json();
    })
    .then(redditNames => {
        //this is there I set my subreddits state variable to the array of strings
        this.setState({subreddits: redditNames.names});
    })
  }
  
  getSubredditInfo(subreddit){
     console.log(subreddit);
  }
  
  render() {
    return <div className="redditResults">
      <h1>Top 10 subreddits for that topic</h1>
      <ul>
        { 
            this.state.subreddits.map((subreddit)=>{
                return (<li key={subreddit.toString()} onClick={()=>this.getSubredditInfo(subreddit)}>{subreddit}</li>);
            })
        }
      </ul>
    </div>;
  }
}

ReactDOM.render(
  <App/>,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

请立即检查onClick事件处理程序。它是一个箭头函数,现在用您的getSubredditInfo调用subreddit函数。这样您就可以到达那里。

因此,它与调用处理程序将数据传递到处理程序的方式基本不同。

它可以按预期工作。

答案 1 :(得分:0)

您是否要这样做?我不确定您要做什么。

getSubredditInfo(e, subreddit) {
  console.log(subreddit)
}

render() {
  const { subreddits } = this.state
  var subredditsArray = subreddits.map(subreddit => (
    <li 
      key={subreddit.toString()} 
      onClick={(e) => {
        this.getSubredditInfo(e, subreddit)
      }}
    >
      {subreddit}
    </li>
  ))

  return (
    <div className="redditResults">
      <h1>Top 10 subreddits for that topic</h1>
      <ul>{subredditsArray}</ul>
    </div>
  );
}

主要目的是将您的子reddit传递给onClick函数,以便您在单击该项时会收到该值。


如果仍然出现错误,请尝试此操作并告诉我发生了什么事。

render() {
  const { subreddits } = this.state
  var subredditsArray = subreddits.map(subreddit => (
    <li 
      key={subreddit.toString()} 
      onClick={(e) => {
        console.log(subreddit.toString())
      }}
    >
      {subreddit}
    </li>
  ))

  return (
    <div className="redditResults">
      <h1>Top 10 subreddits for that topic</h1>
      <ul>{subredditsArray}</ul>
    </div>
  );
}

答案 2 :(得分:0)

您可以使用lamda函数或为具有getSubredditInfo函数的值的项列表制作组件

getSubredditInfo(value) {}

render() {

  var subredditsArray = this.state
   .subreddits.map((subreddit, i) => 
     (<li key={i} 
          onClick={() => this.getSubredditInfo(subreddit)}>{subreddit}</li>));

  return (
    <div className="redditResults">
      <h1>Top 10 subreddits for that topic</h1>
      <ul>{subredditsArray}</ul>
    </div>
  );
}

答案 3 :(得分:0)

1)密钥应通过数组中对象的ID来获取。或者,您可以结合使用这两个属性来创建唯一的密钥,以便更好地处理重新渲染。

如果您有字符串数组,则可以使用字符串值+索引的组合来创建唯一值,尽管不建议使用index。

下面给出一个简单的例子。

2)更好的方法可能是将map函数移至另一个函数,然后在render函数中调用该函数,这将返回所需的JSX。它将清除您的渲染功能。

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      subredditsObjArray: [
        { id: 1, value: 'A'},
        { id: 2, value: 'B'},
        { id: 3, value: 'C'},
        { id: 4, value: 'D'}
        ],
      subredditsArray: ['A', 'B', 'C', 'D'],
      selectedValue: ''
    };
  }

  getSubredditInfo = (subreddit) => {
    console.log(subreddit)
    this.setState({
      selectedValue: ((subreddit && subreddit.id) ? subreddit.value : subreddit),
    });
  }

  render() {
    return (
      <div className="redditResults">
        <p>Selected Value: {this.state.selectedValue}</p>
        <h1>Top {this.state.subredditsArray.length || '0'} subreddits for that topic</h1>
        <p>With Objects Array</p>
        <ul>
          {
            this.state.subredditsObjArray
              && this.state.subredditsObjArray.map(redditObj => {
                return (<li key={redditObj.id}><button onClick={() => this.getSubredditInfo(redditObj)}>{redditObj.value || 'Not Found'}</button></li>);
              })
          }
        </ul>
        <br />
        <p>With Strings Array</p>
        <ul>
          {
            this.state.subredditsArray
              && this.state.subredditsArray.map((reddit, index) => {
                return (<li key={reddit + '-' + index}><button onClick={() => this.getSubredditInfo(reddit)}>{reddit || 'Not Found'}</button></li>);
              })
          }
        </ul>
      </div>
    );
  }

}

ReactDOM.render(
  <App etext="Edit" stext="Save" />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>