React/Redux技术求助:通过onClick及Reducer更新组件状态的方法及排查
Hey there! I totally get these confusions—Redux's data flow can feel tricky when you're just starting out. Let's walk through both of your questions with concrete examples tailored to your price estimate project.
1. Triggering Reducer Updates via onClick Events
The core idea here is: your component dispatches an action, and the reducer listens to that action to update the state. Here's how to wire this up step by step:
First: Define an Action Creator
An action creator is just a function that returns an action (a plain object with a type field, and optional data). Let's make one for updating your price state:
// actions/priceActions.js import * as ActionTypes from '../actiontypes/ActionTypes'; // This creator takes the new price data and wraps it into an action export const updateItemPrice = (itemId, newPrice) => { return { type: ActionTypes.UPDATE_ITEM_PRICE, // Match this type in your reducer later payload: { itemId, newPrice } // This is the data we'll pass to the reducer }; };
Second: Dispatch the Action from Your Button's onClick
If you're using functional components (the modern approach), use the useDispatch hook from react-redux to get access to the dispatch function:
// components/PriceEstimate.js import { useDispatch } from 'react-redux'; import { updateItemPrice } from '../actions/priceActions'; const PriceEstimate = ({ items }) => { const dispatch = useDispatch(); return ( <div> {items.map(item => ( <div key={item.id}> <span>Current Price: ${item.price}</span> <button onClick={() => dispatch(updateItemPrice(item.id, item.price + 10))} // Dispatch the action when clicked—here we're adding $10 as an example > Increase Price </button> </div> ))} </div> ); }; export default PriceEstimate;
If you're using class components, use the connect higher-order component to inject the dispatch function or your action creator directly:
// components/PriceEstimate.js import { connect } from 'react-redux'; import { updateItemPrice } from '../actions/priceActions'; class PriceEstimate extends React.Component { render() { const { items, updateItemPrice } = this.props; return ( <div> {items.map(item => ( <div key={item.id}> <span>Current Price: ${item.price}</span> <button onClick={() => updateItemPrice(item.id, item.price + 10)} > Increase Price </button> </div> ))} </div> ); } } // Connect the action creator to the component's props export default connect(null, { updateItemPrice })(PriceEstimate);
2. Passing Action Data to Your Reducer
Now that you're dispatching actions with data, your reducer needs to listen for the action type and use the payload to update the state. Remember: never mutate the original state—always return a new object/array.
Here's how to adjust your reducer:
// reducers/priceReducer.js import * as ActionTypes from '../actiontypes/ActionTypes'; import data from '../data/data'; // Your initial data const initialState = { items: [...data] // Copy initial data to avoid mutating the original }; const priceReducer = (state = initialState, action) => { switch(action.type) { case ActionTypes.UPDATE_ITEM_PRICE: // Use the payload from the action to find and update the correct item const updatedItems = state.items.map(item => { if (item.id === action.payload.itemId) { // Return a new item object with the updated price return { ...item, price: action.payload.newPrice }; } return item; // Leave other items unchanged }); // Return a new state object with the updated items array return { ...state, items: updatedItems }; default: return state; // Always return the original state for unrecognized actions } }; export default priceReducer;
Quick Checks to Avoid Common Issues
- Double-check that your
ActionTypesconstants are spelled exactly the same in both your action creator and reducer (typos are a super common culprit!). - Make sure your app is wrapped in Redux's
Providercomponent at the root level—this is how components get access to the store:// index.js import { Provider } from 'react-redux'; import store from './store'; // Your configured Redux store ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ); - Always return a new state object in your reducer—never do something like
state.items[0].price = 10(this mutates the original state, which breaks Redux's immutability rules).
内容的提问来源于stack exchange,提问作者aromanarguello

