简体   繁体   中英

Add prop when onClick in ReactJS

I would like to change current li item color when I click it.

How to add prop to item(using array map), when I click it? I use styled-components

const Li = styled.li`
  color: ${props => (props.checked ? "red" : "green")};
`;

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: "",
      items: []
    };
  }

  render() {
    const ShowItems = this.state.items.map((item, index) => {
      return (
        <Li key={index}>
          {item}
          <button onClick={() => this.deleteItemHandler(index)}> Delete</button>
        </Li>
      );
    });

    return (
      <Wrapper>
        <AddItem
          addItemHandler={this.addItem}
          InputValue={this.state.value}
          InputValueHandler={this.inputValue}
        />
        {ShowItems}
      </Wrapper>
    );
  }
}

So you need keep track of the active index, and use it too change the color of the active component color.

state ={
 activeIndex: void 0 
}

const Li = styled.li`
   color: ${props => props.checked ? "red" : "green"};
   ;`

deleteItemHandler = (index) => {
  this.setState({
   activeIndex: index
  })
}


render() {
    const ShowItems = this.state.items.map((item, index) => {
      return (
        <Li key={index} checked={index === this.state.activeIndex} > {item} < button onClick={() => this.deleteItemHandler(index)
        }> Delete</button ></Li >
      )
    })

    return (
      <Wrapper>
        <AddItem
          addItemHandler={this.addItem}
          InputValue={this.state.value}
          InputValueHandler={this.inputValue}
        />
        {ShowItems}
      </Wrapper>
    );

Try this

     const Li = styled.li`
       color: ${props => props.checked ? "red" : "green"};
       ;`

    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          value: "",
          items: [],
          currentChecked: null
        };
      }

     render() {
        const ShowItems = this.state.items.map((item, index) => {
          return (
            <Li key={index} checked={index === this.state.currentChecked} >
              {item} 
              <button onClick={() => this.setState({currentChecked: index})}>Delete</button >
            </Li >
           )
        })

        return (
          <Wrapper>
            <AddItem
              addItemHandler={this.addItem}
              InputValue={this.state.value}
              InputValueHandler={this.inputValue}
            />
            {ShowItems}
          </Wrapper>
        );

Check out this code working on CodeSandBox

import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import styled from "styled-components";

const Li = styled.li`
  color: ${props => (props.checked ? "red" : "green")};
`;

class App extends Component {
  state = {
    value: "",
    items: [],
    selected: -1
  };

  handleChange = e => {
    this.setState({
      [e.currentTarget.name]: e.currentTarget.value
    });
  };

  handleAdd = () => {
    const { items, value } = this.state;
    this.setState({
      items: [...items, value],
      value: ""
    });
  };

  handleRemove = index => {
    const { items, selected } = this.state;
    items.splice(index, 1);
    if (index < selected) index = selected - 1;
    if (index === selected) index = -1;
    if (index > selected) index = selected;
    this.setState({
      items: items,
      selected: index
    });
  };

  handleActiveItem = index => {
    this.setState({ selected: index });
  };

  render() {
    const { value, items, selected } = this.state;
    return (
      <div>
        <input
          type="text"
          value={value}
          name="value"
          onChange={this.handleChange}
        />
        <button
          style={{ margin: "0px 5px" }}
          disabled={!value}
          className="btn btn-sm btn-success"
          onClick={this.handleAdd}
        >
          +
        </button>
        <ul className="li">
          {items.map((item, index) => (
            <Li key={index} checked={selected === index}>
              <span onClick={() => this.handleActiveItem(index)}>{item}</span>
              <button
                style={{ margin: "1px 5px" }}
                className="btn btn-sm btn-danger"
                onClick={() => this.handleRemove(index)}
              >
                X
              </button>
            </Li>
          ))}
        </ul>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Ignore the handlers if you don't need them. Thanks to this effort I learnt about styled-components and discovered CodeSandBox.

EDIT :

  • Added a <span> inside <li> to avoid nested onClick , previously <li> (parent) and <button> (child) both had onClick attribute. On button Click two onClick events were fired resulting in unexpected behaviour in some use cases. You must correct this in your code .
  • Added logic to keep item selected when an item before it is deleted.
  • Added button validation to avoid adding empty string/items in list.
  • Also updated CodeSandBox Code to reflect above changes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM