const {
Provider,
connect,
useSelector,
useDispatch,
} = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const initialState = {
items: [{ id: 1, name: 'item 1' }],
};
//action types
const DELETE = 'DELETE';
//action creators
const deleteItem = (id) => ({
type: DELETE,
payload: id,
});
const reducer = (state, { type, payload }) => {
console.log('action:', type, 'payload:', payload);
return state;
};
//creating store with redux dev tools
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
initialState,
composeEnhancers(
applyMiddleware(() => (next) => (action) =>
next(action)
)
)
);
//you should use reselect here but for simplicity I didn't
const mapStateToProps = (state, { id }) => ({
item: state.items.find((item) => item.id === id),
});
//if mapDispatchToProps is undefined then react-redux
// will add dispatch to props, here is how you can delete
const ItemMapDispatchUndefined = ({ item, dispatch }) => (
<button onClick={() => dispatch(deleteItem(item.id))}>
undefined - delete {item.name}
</button>
);
const ConnectedDispatchUndefined = connect(mapStateToProps)(
ItemMapDispatchUndefined
);
//if mapDispatchToProps is an object then react-redux
// will take the properties of that object and if a
// property is a functoin it will wrap that function
// in a new function that will automatically dispatch
// the return value when that function is called
const ItemMapDispatchObject = ({ item, deleteItem }) => (
// no dispatch needed but still need to pass id to deleteItem
<button onClick={() => deleteItem(item.id)}>
object - delete {item.name}
</button>
);
const ConnectedDispatchObject = connect(mapStateToProps, {
deleteItem,
})(ItemMapDispatchObject);
//if mapDispatchToProps is a function then that function needs
// to return an object where each property of that object is a
// function that will dispatch an action. These properties
// will be added to component props by react-redux
const ItemMapDispatchFunction = ({ item, deleteItem }) => (
// no dispatch needed and no id needs to be passed
<button onClick={deleteItem}>
function - delete {item.name}
</button>
);
const ConnectedItem3 = connect(
mapStateToProps,
(dispatch, { id }) => ({
deleteItem: () => dispatch(deleteItem(id)),
})
)(ItemMapDispatchFunction);
//using hooks (not using connect at all)
const Hooks = ({ id }) => {
//should use reselect but for simplicity not used
const item = useSelector((state) =>
state.items.find((item) => item.id === id)
);
const dispatch = useDispatch();
return (
<button onClick={() => dispatch(deleteItem(item.id))}>
hooks - delete {item.name}
</button>
);
};
const App = () => {
return (
<div>
<ConnectedDispatchUndefined id={1} />
<ConnectedDispatchObject id={1} />
<ConnectedItem3 id={1} />
<Hooks id={1} />
</div>
);
};
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="root"></div>