简体   繁体   中英

Changing Redux store using input

I'm really new to React, Typescript and Redux, < a week using them.

What I need, is to store a "userName" on Redux's storage, in order to validate it against other values in the storage. My problem specifically is not being able to store the userName, mostly because all examples use class based components, while I'm using functional ones. Here's what I have as of now:

 //User input component import React, { useState } from "react"; import { connect } from "react-redux"; import { bindActionCreators } from "redux"; import * as actions from "../../actions"; import Button from "@material-ui/core/Button"; import TextField from "@material-ui/core/TextField"; import Dialog from "@material-ui/core/Dialog"; import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogContentText from "@material-ui/core/DialogContentText"; import DialogTitle from "@material-ui/core/DialogTitle"; import { ApplicationStateInterface } from "../../combineReducers"; import { Box } from "@material-ui/core"; interface channelCreatorInterface { open: boolean; hideChannelCreator?: any; handleFormChange?: any; } const mapStateToProps = ( state: ApplicationStateInterface, ownProps: channelCreatorInterface ) => { return { ...ownProps, }; }; const mapDispatchToProps = (dispatch: any) => ({ hideChannelCreator() { dispatch(actions.hideChannelCreator()); }, }); const ChannelCreator = (props: channelCreatorInterface) => { return ( <div> <Dialog open={props.open} onClose={props.hideChannelCreator} aria-labelledby='form-dialog-title'> <DialogTitle id='form-dialog-title'>Create channel name</DialogTitle> <DialogContent> <DialogContentText> To create a channel name, please enter your desired name here. We will check for availability. </DialogContentText> <TextField autoFocus margin='dense' id='name' label='Channel name' type='username' fullWidth onChange= {HERE IS THE EVENT I NEED TO CAPTURE} /> </DialogContent> <DialogActions> <Button color='primary' onClick={props.hideChannelCreator}> Cancel </Button> <Box id='saveButton'> <Button variant='contained' color='primary'> Save </Button> </Box> </DialogActions> </Dialog> </div> ); }; export default connect(mapStateToProps, mapDispatchToProps)(ChannelCreator);


 //Form change action import { makeActionCreator } from "../utility"; export const HANDLE_FORM_CHANGE = "HANDLE_FORM_CHANGE"; export const handleFormChange = makeActionCreator( HANDLE_FORM_CHANGE, "payload" );


 //Reducer import { constants } from "os"; import { Reducer } from "redux"; import { CREATE_CHANNEL, DISPLAY_CHANNEL_CREATOR, HIDE_CHANNEL_CREATOR, HANDLE_FORM_CHANGE, } from "../actions"; export interface channelCreatorInterface { open: boolean; state: "idle" | "saving" | "correctly saved"; channelName: ""; } export const channelCreatorInitialState: channelCreatorInterface = { open: false, state: "idle", channelName: "", }; export const channelCreatorReducer: Reducer<any, any> = ( channelCreatorState: channelCreatorInterface = channelCreatorInitialState, action: { type: any; state: channelCreatorInterface } ) => { switch (action.type) { case CREATE_CHANNEL: return { ...channelCreatorState, state: "saving", }; case DISPLAY_CHANNEL_CREATOR: return { ...channelCreatorState, open: true, }; case HIDE_CHANNEL_CREATOR: return { ...channelCreatorState, open: false, }; case HANDLE_FORM_CHANGE: return { ...channelCreatorState, channelName: "", }; default: return channelCreatorState; } };


First, let's go to your question:

Your reducer would need to use a payload from your action:


        case HANDLE_FORM_CHANGE:
            return {
                ...channelCreatorState,
                channelName: action.payload,
            };

and in your component, you would then use an event handler to dispatch an action with that payload:

const mapDispatchToProps = (dispatch: any) => ({
    // ...
    setChannelName: (channelName: string) => dispatch({ type: HANDLE_FORM_CHANGE, payload: channelName })
});
// in your component:
                    <TextField
                        autoFocus
                        margin='dense'
                        id='name'
                        label='Channel name'
                        type='username'
                        fullWidth
            onChange={event => props.setChannelName(event.target.value)}
                    />

But please note, that this is a very outdated style of writing redux. For one, we recommend using the react-redux hooks useSelector and useDispatch , which can replace connect in function components. Also, we recommend using redux toolkit instead of writing plain redux reducers by hand, as that will save you a lot of code and also help a lot with the typescript typings.

If you are looking for an up-to-date tutorial, the official Essentials Tutorial is the best place to start.

Also, if you have any quick questions that don't make good material for a stackoverflow questions, be sure to visit us over in the official redux channel on the reactiflux discord server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM