Redux 能够将字符设置为数组,但是删除操作似乎没有到达 reducer

Posted

技术标签:

【中文标题】Redux 能够将字符设置为数组,但是删除操作似乎没有到达 reducer【英文标题】:Redux is able to set characters to an array however the remove action does not seem to reach the reducer 【发布时间】:2021-08-28 09:58:55 【问题描述】:

我正在使用 redux 在用户键入或删除字符数组时更新它,这样当用户正确键入整个短语时,我可以设置成功标志。

到目前为止,当输入字符时,redux 类型 SET_INPUT 会触发并更新我的状态,但不幸的是,我的 REMOVE_INPUT 似乎没有触发,但它确实会执行操作。

我的减速机: 从 "../types" 导入 GET_PHRASE, SET_LOADING, SET_INPUT, REMOVE_INPUT ;

const initialState = 
    level: 1,
    phrase: null,
    scrambledPhrase: null,
    words: [],
    input: [],
    goal: [],
    success: false,
    loading: false,
;

export const phraseReducer = (state = initialState, action) => 
    switch (action.type) 
        case GET_PHRASE:
            return 
                ...state,
                phrase: action.payload.sentence,
                scrambledPhrase: action.payload.scrambledPhrase,
                words: action.payload.phrase.split(" "),
                goal: action.payload.phrase.split(""),
                loading: false,
            ;
        case SET_INPUT:
            console.log("setting input");
            return 
                ...state,
                input: [...state.input, action.payload],
            ;
        case REMOVE_INPUT:
            console.log("removing input");
            return 
                ...state,
                input: [...state.input.slice(0, -1)],
            ;
        case SET_LOADING:
            return 
                ...state,
                loading: true,
            ;
        default:
            return state;
    
;

我的行动:

import  GET_PHRASE, SET_LOADING, SET_INPUT, REMOVE_INPUT  from "../types";
import axios from "axios";

export const getPhrase = (level) => async (dispatch) => 
    try 
        setLoading();

        await axios
            .get(`MY ROUTE`)
            .then((res) => 
                // console.log(res);
                const sentence = res.data.data.phrase;
                const scrambledSentence = scramblePhrase(
                    res.data.data.phrase
                );

                dispatch(
                    type: GET_PHRASE,
                    payload: 
                        phrase: phrase.toLowerCase(),
                        scrambledPhrase: scrambledPhrase.toLowerCase(),
                    ,
                );
            );
     catch (err) 
        console.error(err);
    
;

// SET INPUT
export const setInput = (input) => async (dispatch) => 
    try 
        dispatch(
            type: SET_INPUT,
            payload: input,
        );
     catch (err) 
        console.error(err);
    
;

// REMOVE INPUT
export const removeInput = () => 
    try 
        console.log("remove reached in actions");
        return 
            type: REMOVE_INPUT,
        ;
     catch (err) 
        console.error(err);
    
;

// SET LOADING
export const setLoading = () => 
    console.log("Loading...");
    return 
        type: SET_LOADING,
    ;
;

我的组件输入一个字符:

import React,  useState  from "react";

// redux imports
import  connect  from "react-redux";
import  setInput, removeInput  from "../redux/actions/phraseActions";
import PropTypes from "prop-types";

const Character = ( character, hasSpace, setInput ) => 
    const [success, setSuccess] = useState();

    const handleChange = (e) => 
        if (e.target.value === character) 
            // console.log("Success");
            setSuccess(true);
         else 
            setSuccess(false);
        
    ;

    const keyedDown = (e) => 
        // check for space or a letter
        if (e.keyCode === 32 || (e.keyCode > 64 && e.keyCode < 91)) 
            setInput(String.fromCharCode(e.keyCode).toLowerCase());
        
        // check for backspace
        else if (e.keyCode === 8) 
            removeInput();
        
    ;
    return (
        <div
            className=`character $
                success ? "success" : hasSpace ? "space" : ""
            `
        >
            <input
                type="text"
                name="name"
                required
                maxLength="1"
                size="1"
                onChange=handleChange
                onKeyDown=keyedDown
                className="input"
                autoComplete="off"
            ></input>
        </div>
    );
;

Character.propTypes = 
    setInput: PropTypes.func.isRequired,
    removeInput: PropTypes.func.isRequired,
;

const mapStateToProps = (state) => (
    // define state
    phrase: state.phrase,
);

export default connect(mapStateToProps,  setInput, removeInput )(Character);

在我的控制台中,您可以看到我到达了哪些点:

【问题讨论】:

【参考方案1】:

在您的事件处理程序中,您没有调用由 connect (props.removeInput) 提供的 removeInput,而是导入的 removeInput 不分派任何内容,只返回一个操作对象,因此我建议将组件定义更改为:

const Character = ( character, hasSpace, setInput, removeInput ) => 

在你的 reducer 中你可以这样做:input: state.input.slice(0, -1), 因为slice 已经返回了数组的浅拷贝,所以不需要用 [...] 复制它

【讨论】:

天啊,我瞎了!谢谢!

以上是关于Redux 能够将字符设置为数组,但是删除操作似乎没有到达 reducer的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ReactJs Redux 中删除/设置状态数组的“null”嵌套属性?

Redux:使用 Redux 更新数组的状态

如何在 redux saga 中调度操作之前将数据设置为 localStorage

意外的 redux 操作调度行为

将字符串转换为数组后从字符串中删除特定项目

Redux 在存储中返回一个空数组 - Reducer 无法正常工作?