我是ReactJS的新手。我正在尝试构建一种在线购物功能,其中我们可以增加数量或减少数量。或使用“删除”按钮直接删除项目。我正在尝试使用console.log(“ delete clicked”,counterId)打印被单击的按钮的ID。在“ 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;
任何帮助将不胜感激!
答案 0 :(得分: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}!
counters.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>
);
}
答案 1 :(得分: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>