使用输入更改 Redux 存储

Changing Redux store using input

真的 是 React、Typescript 和 Redux 的新手,使用它们不到一周。

我需要的是在 Redux 的存储中存储一个“用户名”,以便根据存储中的其他值验证它。我的问题具体是无法存储用户名,主要是因为所有示例都使用基于 class 的组件,而我使用的是功能性组件。这是我目前拥有的:

//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;
    }
};


首先,让我们回到您的问题:

您的减速器需要使用您操作中的有效载荷:


        case HANDLE_FORM_CHANGE:
            return {
                ...channelCreatorState,
                channelName: action.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)}
                    />

但请注意,这是一种非常过时的 redux 编写风格。 其一,我们推荐使用 react-redux 钩子 useSelectoruseDispatch,它们可以替代函数组件中的 connect。此外,我们建议使用 redux toolkit 而不是手动编写普通的 redux reducer,因为这将为您节省大量代码,并且还有助于 lot 打字稿打字。

如果您正在寻找 up-to-date 教程,官方 Essentials Tutorial 是最好的起点。

此外,如果您有任何不适合 material Whosebug 问题的快速问题,请务必在 reactiflux discord 服务器上的官方 redux 频道访问我们。