5

i'm trying to create a list of documents dynamically with semantic-ui-react. I'd like to get the document title back when the list item is clicked. According to the documentation: https://react.semantic-ui.com/elements/list

there is an onItemClick prop for this reason, however when im using it i get a warning when it's rendered:

Warning: Failed prop type: Prop onItemClick in List conflicts with props: children. They cannot be defined together, choose one or the other.

Also clicking on the list item does nothing (atm i just want to log the doc title to the console). Here is the code:

handleListItemClick(event, data) {
  console.log("list item clicked: " + data.value);
}


buildResultsContainer() {
    return this.props.listOfResults.map((document,index) =>
      {
        return (
            <List.Item
              as='a'
              key={index}>
                <Icon name='file' />
                <List.Content>
                  <List.Header>{document.properties.title}</List.Header>
                  <List.Description>
                    {document.properties.description}
                  </List.Description>
                </List.Content>
            </List.Item>
      );
      }
    );
  }

  render() {
    return (
      <div>
        <List onItemClick={this.handleListItemClick}>
          {this.buildResultsContainer()}
        </List>
      </div>
    )
  }

Can you please tell me how to use properly the onItemClick prop for the List component?

Less important, do you have any tip how to refactor the list rendering? Just wanted to keep the render function short and clean, but this function call looks a bit overkill....

Thanks a lot!

inspiral
  • 611
  • 1
  • 7
  • 15

1 Answers1

5

I think maybe the intent when using onItemClick is that you would use the items prop on List since then you wouldn't have any children e.g.

render() {
    const items = this.props.listOfResults.map(document => {
      return {
        icon: 'file',
        content: document.properties.title,
        description: document.properties.description,
        onClick: e => console.log(document.title)
      }
    });

    return <List items={items} />
  }

If you had your listOfResults prop in the above format, you wouldn't even need to do this map and your render function would be super tight:

render() {
  return <List items={this.props.listOfResults} />;
}

Alternately, List.Item takes an onClick prop that you could define in your buildResultsContainer() function. Because each onClick function is unique based on the current document object, you will need to use an anonymous function to call your handleClick function as follows:

<List.Item
  onClick={() => this.handleClick(document.title)}
  ...etc
/>

You would then have:

handleClick = docTitle => {
  console.log(docTitle);
};

If what you wanted was obtainable from event.target, you could just pass the reference of handleClick to the onClick i.e.

handleClick = event => {
    console.log(e.target.innerText);
};

<List.Item
  onClick={this.handleClick}
/>
Anthony
  • 6,422
  • 2
  • 17
  • 34
  • Thanks! I tried so far the alternate idea: if i give an `onClick` for the `List.item` , the function is called immediately when the list is rendered. Which is kinda strange. – inspiral Mar 25 '18 at 23:06
  • 1
    ` console.log(document.title)} />` ? – Anthony Mar 25 '18 at 23:07
  • In this case it works well. Strange (at least to my current reactjs knowledge) why `onClick={this.handleListItemClick(document.properties.title)}` gives different result. – inspiral Mar 25 '18 at 23:22
  • 1
    because what you are passing there is function invocation, as opposed to reference to the function. I will add an example – Anthony Mar 26 '18 at 00:06
  • Makes complete sense, it explains also why it was called during rendering in my attempt. Both of your suggestions worked flawlessly, thanks a lot! – inspiral Mar 26 '18 at 13:54
  • However im still puzzled why doesn’t my original idea work (example for solution): https://codepen.io/gaearon/pen/xEmzGg?editors=0010 this snippet is from the official react docs: https://reactjs.org/docs/handling-events.html Both, my original and your suggestion can be found on this page. I read it back and forth, but still don’t get why the example works and mine not. Is it because if there is a need to pass an argument to the function and using the `()` after function name interpreted as function call instead of reference? – inspiral Mar 26 '18 at 13:54
  • @inspiral the first example is from vanilla HTML as opposed to React JSX – Anthony Mar 26 '18 at 16:57
  • This is the one i was referring to: https://codepen.io/gaearon/pen/xEmzGg?editors=0010 – inspiral Mar 26 '18 at 18:39
  • That is also passing just a function reference, `this.handleClick`; it is not invoking it with `()` – Anthony Mar 26 '18 at 21:56