#javascript #reactjs #onclick #setstate #map-function
#javascript #reactjs #onclick #setstate #map-функция
Вопрос:
У меня есть приложение для покупок в REACT js. Я показываю все товары с помощью функции .map(), а также показываю кнопку «ДОБАВИТЬ в корзину» перед каждым товаром. При нажатии кнопки ДОБАВИТЬ в корзину btn добавляется выбранный идентификатор продукта в локальном хранилище, после чего я отображаю эти выбранные товары в корзине покупок, извлекая идентификаторы из localStorage. Все работает нормально.
Теперь я хотел отключить кнопку «ДОБАВИТЬ в корзину» (только для выбранного товара) при нажатии на нее один раз. Я сделал это, установив state, но на самом деле он отключает ВСЕ кнопки «ДОБАВИТЬ в корзину» перед всеми ПРОДУКТАМИ вместо отключения только выбранной кнопки.
Я много искал эту проблему, и решение, которое я получил везде, — это просто установить значение true / false для включения / выключения кнопки. Я сделал это, но бесполезно, потому что он делает это для ВСЕХ продуктов на этой странице. Пожалуйста, помогите мне, что делать.
Вот мой код REACT JS:
export default class SpareParts extends Component
{
constructor()
{
super()
this.state = {
spareParts: [],
cart: [],
inCart: false,
disabledButton: false
};
this.ViewDeets = this.ViewDeets.bind(this);
this.AddToCart = this.AddToCart.bind(this);
}
ViewDeets= function (part)
{
this.props.history.push({
pathname: '/partdetails',
state: {
key: part
}
});
}
AddToCart(param, e)
{
var alreadyInCart = JSON.parse(localStorage.getItem("cartItem")) || [];
alreadyInCart.push(param);
localStorage.setItem("cartItem", JSON.stringify(alreadyInCart));
this.setState({
inCart: true,
disabledButton: true
})
}
componentDidMount()
{
console.log("Showing All Products to Customer");
axios.get('http://localhost/Auth/api/customers/all_parts.php', {
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
}} )
.then(response =>
{
this.setState({
spareParts :response.data.records
});
})
.catch(error => {
if (error) {
console.log("Sorry Cannot Show all products to Customer");
console.log(error);
}
});
}
render()
{
return (
<div id="profileDiv">
{this.state.spareParts.map( part =>
<Col md="3" lg="3" sm="6" xs="6">
<Card>
<Image src={"data:image/png[jpg];base64," part.Image}
id="partImg" alt="abc" style={ {width: "90%"}} />
<h4> {part.Name} </h4>
<h5> Rs. {part.Price} </h5>
<h5> {part.Make} {part.Model} {part.Year} </h5>
<h5> {part.CompanyName} </h5>
<button
onClick={()=> this.ViewDeets(part) }>
View Details
</button>
<button onClick={() => this.AddToCart(part.SparePartID)}
disabled={this.state.disabledButton ? "true" : ""}>
{!this.state.inCart ? ("Add to Cart") : "Already in Cart"}
</button>
</Card>
</Col>
)}
</div>
);
}
}
Ответ №1:
Вам нужно отключать только одну кнопку за раз? Если это так, измените свое состояние на не логическое значение, а число, указывающее, какая кнопка отключена. Затем при рендеринге отключайте только в том случае, если отображаемая вами кнопка имеет тот же индекс, что и в состоянии.
this.state = {
disabledButton: -1
// ...
}
// ...
AddToCart(index, param, e) {
//...
this.setState({
inCart: true,
disabledButton: index
})
}
// ...
{this.state.spareParts.map((part, index) => {
// ...
<button onClick={() => this.AddToCart(index, part.SparePartID)}
disabled={this.state.disabledButton === index}>
{!this.state.inCart ? ("Add to Cart") : "Already in Cart"}
</button>
})}
Если вместо этого каждая кнопка должна быть отключена независимо одновременно, измените свое состояние на массив логических значений той же длины, что и запасные части, и в методе рендеринга попросите каждую кнопку посмотреть, следует ли ее отключить в этом массиве.
this.state = {
spareParts: [],
disabledButtons: [],
// ...
}
// ...
axios.get('http://localhost/Auth/api/customers/all_parts.php', {
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
}} )
.then(response =>{
this.setState({
spareParts: response.data.records,
disabledButtons: new Array(response.data.records.length).fill(false)
});
});
// ...
AddToCart(index, param, e) {
//...
this.setState(oldState => {
const newDisabledButtons = [...oldState.disabledButtons];
newDisabledButtons[index] = true;
return {
inCart: true,
disabledButtons: newDisabledButtons,
}
});
}
// ...
{this.state.spareParts.map((part, index) => {
// ...
<button onClick={() => this.AddToCart(index, part.SparePartID)}
disabled={this.state.disabledButtons[index]>
{!this.state.inCart ? ("Add to Cart") : "Already in Cart"}
</button>
})}
Комментарии:
1. Спасибо за ответ. Да, я хочу отключить каждую кнопку независимо одновременно. Итак, как мне изменить состояние на массив логических значений? Пожалуйста, уточните.
2. @YellowMinion я добавил в пример с массивом
3. Еще раз спасибо. Как мне отключить эту нажатую кнопку в методе AddToCart?
4. Вы устанавливаете состояние с помощью массива, для которого этот индекс переключен на true . Я отредактировал пример.
5. Удивительный и очень полезный ответ. Именно то, что я искал, но почему-то я не понимаю, как я мог бы немедленно обновить кнопку. У меня есть таблица с большим количеством кнопок, и они повторно отображаются только тогда, когда я щелкаю из строки вместо этого после нажатия кнопки. Любые советы, как запустить повторный рендеринг кнопки, которая теперь должна быть отключена?