React中修改按钮文本后,如何触发Redux-thunk的dispatch?
Let's break down the issues in your current code and fix them step by step:
The Immediate Fix
The core problem in your updateCart function is that in the if branch, you defined an arrow function but never executed it—so the addToCart dispatch never runs. Plus, we can clean up the logic to ensure the button text updates first, then the Redux action fires.
Here's the corrected updateCart method:
updateCart(event, id) { // Store the button element in a variable to avoid potential target changes const cartButton = event.target; if (cartButton.textContent.trim() === 'Add to cart') { // First update the button text immediately cartButton.textContent = 'Remove from cart'; // Trigger the Redux dispatch to add the item const currentCount = this.props.cartcount.cartcount; this.props.addToCart(id, currentCount); } else { // Update text first, then dispatch the removal cartButton.textContent = 'Add to cart'; const currentCount = this.props.cartcount.cartcount; this.props.subtractFromCart(id, currentCount); } }
Key Fixes:
- Executed the dispatch: Removed the unused arrow function wrapper around
this.props.addToCart—now it runs immediately after updating the button text. - Trimmed text check: Added
.trim()to handle any accidental whitespace in the button text, making the check more reliable. - Stored the button element: Using
cartButtoninstead of repeatingevent.targetis a safer practice (prevents issues if the event target changes unexpectedly).
A Better Approach: Avoid Relying on DOM Text for State
While the above fix works, relying on the button's text content to determine its state is fragile (e.g., if you later add localization or modify the text). Instead, drive the button state from your Redux store.
Step 1: Pass Cart Status to RenderBooks
In your Books component's render method, check if each book is already in the cart, then pass that state to RenderBooks:
render() { const count = this.props.cartcount.cartcount; // Assuming you have a cartItems array in your Redux state with book IDs const { cartItems } = this.props; const bookElements = this.props.books.books.map((book, index) => { const isInCart = cartItems.some(item => item.id === book.id); return ( <div key={index} className="col-8 col-md-4 col-lg-3"> <RenderBooks book={book} updateCart={this.updateCart} isInCart={isInCart} /> </div> ); }); // ... rest of your render code }
Step 2: Set Button Text from Redux State
Update RenderBooks to use the isInCart prop instead of hardcoding the initial text:
function RenderBooks({book, updateCart, isInCart}) { return( <Card className="allbooks"> {/* ... existing card content ... */} <form> <Button className="add-to-cart" style={{textDecoration:'none'}} color="link" onClick={(e) => updateCart(e, book.id)} > {isInCart ? 'Remove from cart' : 'Add to cart'} </Button> </form> </Card> ); }
Step 3: Update updateCart to Use Redux State
Now your updateCart function can rely on the Redux state instead of DOM text:
updateCart(event, id) { const { cartItems } = this.props; const isInCart = cartItems.some(item => item.id === id); const cartButton = event.target; if (!isInCart) { cartButton.textContent = 'Remove from cart'; const currentCount = this.props.cartcount.cartcount; this.props.addToCart(id, currentCount); } else { cartButton.textContent = 'Add to cart'; const currentCount = this.props.cartcount.cartcount; this.props.subtractFromCart(id, currentCount); } }
This approach makes your component more predictable—your UI state is always synced with your Redux store, instead of relying on DOM elements to track state.
内容的提问来源于stack exchange,提问作者Uwem Uke

