Reactjs无法打印id

问题描述 投票:0回答:2

我是ReactJS的新手。我正在尝试构建一种在线购物类型的功能,其中我们可以增加数量并减少它。或者使用“删除”按钮直接删除项目。我正在尝试使用console.log打印单击按钮的id(“delete clicked”,counterId);在“counters.jsx”中。但是有些它每次都给我带来了不确定性。这是我的代码。

counters.jsx

import React,{Component} from 'react';
import Counter from './counter';

class Counters extends Component {
    state = {
        counters:[
            {id:1,value:4},
            {id:2,value:0},
            {id:3,value:3},
            {id:4,value:0}
        ]
    };

    handleDelete=(counterId)=>{
        console.log("delete clicked",counterId);
    }

    render(){
        return (
            <div>
                {this.state.counters.map(counter=>
                    <Counter key={counter.id} onDelete={this.handleDelete} value={counter.value}/>)}
            </div>
        );
    }
}

export default Counters;

counter.jsx

import React, { Component} from 'react';

class Counter extends Component{
    state={
        value: this.props.value 
    };

    handleIncrement=()=>{
        this.setState({value:this.state.value+1});
    }

    handleDecrement=()=>{       
        this.setState({value:this.state.value-1});
    }

    render(){
        return (
            <React.Fragment>
                <p>
                <span className={this.getBadgeClasses()}>{this.formatCount()}</span>
                <button onClick={this.handleIncrement} className="btn btn-secondary btn-sm m-1">Increment</button>
                <button onClick={this.handleDecrement} className="btn btn-warning btn-sm m-1">Decrement</button>
                <button onClick={()=>this.props.onDelete(this.props.id)} className="btn btn-danger btn-sm m-1">Delete</button>
                </p>
            </React.Fragment>
        );
    }

    getBadgeClasses(){
        let classes="badge m-2 badge-";
        classes+=this.state.value===0?"warning":"primary";
        return classes;
    }

    formatCount(){
        const {value} = this.state;
        return value===0 ? 'Zero': value;
    }
}

export default Counter;

任何帮助都感激不尽!

javascript reactjs
2个回答
0
投票

阅读一次。 https://reactjs.org/docs/lists-and-keys.html#keys-must-only-be-unique-among-siblings

通过上面的示例,Post组件可以读取props.id,但不能读取props.key。

因此,你必须添加props.id = {counter.id}!

counter.jsx之前

render(){
    return (
        <div>
            {this.state.counters.map(counter=>
                <Counter key={counter.id} onDelete={this.handleDelete} value={counter.value}/>)}
        </div>
    );
}

render(){
    return (
        <div>
            {this.state.counters.map((counter, index)=>
                <Counter key={index} id={counter.id} onDelete={this.handleDelete} value={counter.value}/>)}
        </div>
    );
}

0
投票

你没有将counter作为你的Counter组件的道具,你只是通过counter.value。而不是这样做传递counter本身:

<Counter key={counter.id} onDelete={this.handleDelete} counter={counter} /> )}

然后在Counter组件:

state={
      value: this.props.counter.value,
};

此外,如果您在此处分离handleDelete函数并使用其引用,则不会在每个渲染中重新创建它。喜欢:

handleDelete = () => this.props.onDelete( this.props.counter.id );

<button onClick={this.handleDelete} className="btn btn-danger btn-sm m-1">Delete</button>

但是,你的逻辑有些奇怪。您在父组件中有一个状态,然后您还在子组件中保留另一个状态并执行增量,在那里递减。你父母的州不会改变。那是你真正想要的吗?那么,你想要多个计数器并分别保持它们的状态吗?

这是完整的代码:

class Counters extends React.Component {
    state = {
      counters: [
        { id: 1, value: 4 },
        { id: 2, value: 0 },
        { id: 3, value: 3 },
        { id: 4, value: 0 },
      ],
    };

    handleDelete=( counterId ) => {
      console.log( "delete clicked", counterId );
    }

    render() {
      return (
        <div>
          {this.state.counters.map( counter =>
            <Counter key={counter.id} onDelete={this.handleDelete} counter={counter} /> )}
        </div>
      );
    }
}

class Counter extends React.Component {
    state={
      value: this.props.counter.value,
    };

    handleIncrement=() => {
      this.setState( { value: this.state.value + 1 } );
    }

    handleDecrement=() => {
      this.setState( { value: this.state.value - 1 } );
    }

    handleDelete = () => this.props.onDelete( this.props.counter.id );

    render() {
      return (
        <div>
          <p>
            <span className={this.getBadgeClasses()}>{this.formatCount()}</span>
            <button onClick={this.handleIncrement} className="btn btn-secondary btn-sm m-1">Increment</button>
            <button onClick={this.handleDecrement} className="btn btn-warning btn-sm m-1">Decrement</button>
            <button onClick={this.handleDelete} className="btn btn-danger btn-sm m-1">Delete</button>
          </p>
        </div>
      );
    }

    getBadgeClasses() {
      let classes = "badge m-2 badge-";
      classes += this.state.value === 0 ? "warning" : "primary";
      return classes;
    }

    formatCount() {
      const { value } = this.state;
      return value === 0 ? "Zero" : value;
    }
}

ReactDOM.render(
  <Counters />,
  document.getElementById("root")
);
<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="root"></div>

如果你想看到这里是另一种方法:

class Counters extends React.Component {
    state = {
      counters: [
        { id: 1, value: 4 },
        { id: 2, value: 0 },
        { id: 3, value: 3 },
        { id: 4, value: 0 },
      ],
    };

    handleDelete = ( counter ) => {
      const newCounters = this.state.counters.filter( el => el.id !== counter.id );
      this.setState( { counters: newCounters } );
    }

    handleCounter = ( counter, direction ) => {
      const newCounters = this.state.counters.map( ( el ) => {
        if ( el.id !== counter.id ) { return el; }

        return direction === "up" ? { ...counter, value: counter.value + 1 }
          : { ...counter, value: counter.value - 1 };
      } );

      this.setState( { counters: newCounters } );
    }

    render() {
      return (
        <div>
          {this.state.counters.map( counter =>
            ( <Counter
              key={counter.id}
              onDelete={this.handleDelete}
              counter={counter}
              handleCounter={this.handleCounter}
            /> ) )}
        </div>
      );
    }
}

const Counter = ( props ) => {
  const { counter, handleCounter, onDelete } = props;

  function handleIncrement() {
    handleCounter( counter, "up" );
  }

  function handleDecrement() {
    handleCounter( counter );
  }

  function handleDelete() { onDelete( counter ); }

  function getBadgeClasses() {
    let classes = "badge m-2 badge-";
    classes += counter.value === 0 ? "warning" : "primary";
    return classes;
  }

  function formatCount() {
    const { value } = counter;
    return value === 0 ? "Zero" : value;
  }

  return (
    <div>
      <p>
        <span className={getBadgeClasses()}>{formatCount()}</span>
        <button onClick={handleIncrement} className="btn btn-secondary btn-sm m-1">Increment</button>
        <button onClick={handleDecrement} className="btn btn-warning btn-sm m-1">Decrement</button>
        <button onClick={handleDelete} className="btn btn-danger btn-sm m-1">Delete</button>
      </p>
    </div>
  );
};

ReactDOM.render(
  <Counters />,
  document.getElementById("root")
);
<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="root"></div>
© www.soinside.com 2019 - 2024. All rights reserved.