derric-d
derric-d

Reputation: 75

Toggle one list item instead of entire list

I am making a card that lists radio stations and when you click on a station a picture drops down for that list item. all data i am pulling from a json.

I have tried building the list in the toggle.js and in the app.js files

app.js-- div with toggle (its all inside a card..many divs)

           <div class="card-trip-infos">
              <div>
               <Toggle />
              </div>
              <img class="card-trip-user avatar-bordered"/>
            </div>

toggle.js render block:

    state = {
        on: false,
    }
    toggle = () => {
      this.setState({
      on: !this.state.on
      })
    }
    render() {
        return (
          <ul>
              <div>
                  <p>{PostData.radios[0].name}</p>
                  {PostData.radios.map((postDetail, index) => {
                    return <div>
                    <li onClick={this.toggle}>
                      <span id='radioName'>{postDetail.name}</span> <span id='frequency'>{postDetail.frequency}</span>

                    </li>
                    {
                      this.state.on &&  <img src='imagesrc'></img>
                    }


                    </div>
                  })}
              </div>

          </ul>
        )
      }
    }

I dont know what exactly is wrong but i expect to be able to toggle a picture for each list row seperately. i am confused where to iterate over my json and where to plug everything in.

many Thanks!!

Upvotes: 0

Views: 2910

Answers (2)

devserkan
devserkan

Reputation: 17598

Since we don't know your toggle function and all your component we can't make exact suggestions but in order to do what you want here (just toggle the selected item), you have two different approaches.

  1. You can keep the selected state in the component itself.

class App extends React.Component {
  state = {
    cards: [
      { id: 1, name: "foo" },
      { id: 2, name: "bar" },
      { id: 3, name: "baz" }
    ],
  };

  render() {
    const { cards } = this.state;
    return (
      <div>
        {cards.map(card => (
          <Card
            key={card.id}
            card={card}
          />
        ))}
      </div>
    );
  }
}

class Card extends React.Component {
  state = {
    selected: false
  };

  handleSelect = () =>
    this.setState(state => ({
      selected: !state.selected
    }));

  render() {
    const { card } = this.props;
    return (
      <div
        className={this.state.selected ? "selected" : ""}
        onClick={this.handleSelect}
      >
        {card.id}-{card.name}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
.selected {
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

  1. You can keep the selected state in the parent component.

class App extends React.Component {
  state = {
    cards: [
      { id: 1, name: "foo" },
      { id: 2, name: "bar" },
      { id: 3, name: "baz" }
    ],
    selected: {}
  };

  handleSelect = id =>
    this.setState(state => ({
      selected: { ...state.selected, [id]: !state.selected[id] }
    }));

  render() {
    const { cards, selected } = this.state;
    return (
      <div>
        {cards.map(card => (
          <Card
            key={card.id}
            card={card}
            handleSelect={this.handleSelect}
            selected={selected[card.id]}
          />
        ))}
      </div>
    );
  }
}

const Card = ({ card, handleSelect, selected }) => {
  const handleClick = () => handleSelect(card.id);
  return (
    <div className={selected ? "selected" : ""} onClick={handleClick}>
      {card.id}-{card.name}
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
.selected {
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

Upvotes: 2

AshishAgrahari
AshishAgrahari

Reputation: 126

Create a component for individual list item, have a state there which will hold a boolean property to tell whether the image is to be shown or not. Render function will look something like this:

render (
  return (
    <li onClick="this.toggleShowImage()">
      <div> {props.data.name} </div>
      <div> {props.data.frequency} </div>
      {this.state.showImage ? <img src='imageUrl' /> : null }
     </li>
  )
)

Then in toggle.js iterate through your data and create the list components. The render function will look something like below:

render() {
  return (
    <ul>
       {PostData.radios.map((postDetail, index) => {
          return <ListItem key={postDetail.name} data={postDetail} />
       })}
    
    </ul>
   )
}

Upvotes: 0

Related Questions