Redux 状态对象出现多次渲染并变为未定义

huangapple go评论77阅读模式
英文:

Redux state object getting multiple renders and going undefined

问题

Redux中调用的对象重新渲染多次并变为未定义。请帮助我?

我正在使用React和Redux制作一个打字大师工具。

“当文本输入框中提供错误输入时,它会被调用。”

为此,我创建了三个切片,如下所示:

  1. Test-text -- 用于输出测试文本
  2. Input-text -- 用于读取输入文本
  3. Result -- 具有三个参数的对象 { 准确性,WPM 和 WPM 平均值 }

当我从对象中获取准确性时,它重新渲染了4次并变为未定义,请帮助

  1. 100
  2. 99
  3. 99
  4. 未定义
  5. NaN

查看图像描述

请查看我的代码并告诉我为什么会发生这种情况

分享我的GitHub链接:- https://github.com/vishwaTj/Typing_Master

我尝试了很多方法,但我认为这是由于 useEffect 导致的。重新渲染用于匹配输入字符串导致多次状态获取,我不确定。

结果切片的代码:

import { createSlice } from "@reduxjs/toolkit";

const ResultSlice = createSlice({
    name: "Result",
    initialState: {
        Accuracy: 100,
        WPM: 40,
        WPMAverage: []
    },
    reducers: {
        setAccuracy(state, action) {
            return state.Accuracy - 1;
        }
    }
})

export const ResultReducer = ResultSlice.reducer;
export const { setAccuracy } = ResultSlice.actions;

输入文本切片的代码:

import { createSlice } from "@reduxjs/toolkit";

const InputTextSlice = createSlice({
    name: "InputText",
    initialState: "",
    reducers: {
        setValue(state, action) {
            return action.payload;
        }
    }
})

export const InputTextReducer = InputTextSlice.reducer;
export const { setValue } = InputTextSlice.actions;

存储 - 索引文件的代码:

import { configureStore } from "@reduxjs/toolkit";
import { TestTextReducer } from './slices/TestText';
import { InputTextReducer } from "./slices/InputText";
import { ResultReducer } from "./slices/Result";
import { setTest } from "./slices/TestText";
import { setValue } from "./slices/InputText";
import { setAccuracy } from "./slices/Result";

const store = configureStore({
    reducer: {
        TestText: TestTextReducer,
        InputText: InputTextReducer,
        Result: ResultReducer
    }
});

export { store, setTest, setValue, setAccuracy };

渲染来自Redux的状态的组件代码:

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { setValue, setAccuracy } from '../store';

const TextBox = () => {
  
  const Test = useSelector((state) => {
    return state.TestText;
  })

  const InputText = useSelector((state) => {
    return state.InputText;
  })

  const Accuracy = useSelector((state) => {
    console.log(state.Result);
    return  state.Result.Accuracy;
  })

  const dispatch = useDispatch();

  const handleChange = (e) => {
      dispatch(setValue(e.target.value));
  }
 
  useEffect(() => {
    handleMatch();
  }, [handleChange])

  function handleMatch() {
    if (Test === InputText) {
      console.log("a complete match");
      dispatch(setValue(""));
      return;
    } 
    if (Test.includes(InputText)) {
      console.log("good going");
      return;
    }
    else {
      console.log(Accuracy);
      dispatch(setAccuracy());
      return;
    }
  }

  return (
    <div className='TextBox'>
        <h2>Lesson 1</h2>
        <input 
           type="text"
           className='text-input'
           value={Test}
           style={{backgroundColor: "rgba(55,90,127,255)"}}/>
        <input 
           type="text" 
           className='text-input user' 
           onChange={handleChange}
           value={InputText}
           />
        <div className='performance'>
          <h4 className='Tags'>WPM:</h4>
          <h4 className='Tags'>Accuracy:</h4>
          <h4 className='Tags'>Average WPM:</h4>
        </div>
    </div>
  )
}

export default TextBox;
英文:

Object called from Redux Re-rendering multiple times and becomes undefined. Please help me ?

I'm making a typing master tool using React and Redux.

""""" It gets called when a wrong input is given in the text input box """""

For that I created three slices as follows:

  1. Test-text -- To output the testing text
  2. Input-text -- To read the input text
  3. Result -- An object with three parameters { accuracy, WPM and WPMaverage }

When I'm fetching accuracy from the object it is re-rendering 4 times and going undefined please help

  1. 100
  2. 99
  3. 99
  4. undefined
  5. Nan

enter image description here

Please look at my code and let me know why is it happening

Sharing my github link :- https://github.com/vishwaTj/Typing_Master

I tried many things but I think it is due to the useEffect. The re-render used to match the input string is causing multiple state fetches I'm not sure.

Code of the slice for result:

import {createSlice} from &quot;@reduxjs/toolkit&quot;
const ResultSlice = createSlice({
name:&quot;Result&quot;,
//REmember the { gap for curly brace &quot;Oh my god&quot;
initialState: {
Accuracy:100,
WPM:40,
WPMAverage:[]
},
reducers:{
setAccuracy(state,action){
return state.Accuracy-1;
}
}
})
export const ResultReducer = ResultSlice.reducer;
export const {setAccuracy} = ResultSlice.actions;
&#39;&#39;&#39;
code of slice for Input text
&#39;&#39;&#39;
import { createSlice } from &quot;@reduxjs/toolkit&quot;;
const InputTextSlice = createSlice({
name:&quot;InputText&quot;,
initialState:[],
reducers:{
setValue(State,action){
return action.payload;
}
}
})
export const InputTextReducer = InputTextSlice.reducer;
export const {setValue} = InputTextSlice.actions;

code of the Store - index file

import { configureStore } from &quot;@reduxjs/toolkit&quot;;
import {TestTextReducer} from &#39;./slices/TestText&#39;;
import { InputTextReducer } from &quot;./slices/InputText&quot;;
import { ResultReducer } from &quot;./slices/Result&quot;;
import { setTest} from &quot;./slices/TestText&quot;;
import { setValue } from &quot;./slices/InputText&quot;;
import { setAccuracy } from &quot;./slices/Result&quot;;
const store  = configureStore({
reducer:{
TestText:TestTextReducer,
InputText:InputTextReducer,
Result:ResultReducer
}
});
export {store, setTest, setValue, setAccuracy};

code of component which is rendering the state from redux

import React, { useEffect } from &#39;react&#39;;
import { useDispatch,useSelector } from &#39;react-redux&#39;;
import { setValue,setAccuracy } from &#39;../store&#39;;
const TextBox = () =&gt; {
const Test = useSelector((state)=&gt;{
return state.TestText;
})
const InputText = useSelector((state)=&gt;{
return state.InputText;
})
const Accuracy = useSelector((state)=&gt;{
console.log(state.Result);
return  state.Result.Accuracy;
})
const dispatch = useDispatch();
const handleChange=(e)=&gt;{
dispatch(setValue(e.target.value));
}
useEffect(()=&gt;{
handleMatch();
// eslint-disable-next-line react-hooks/exhaustive-deps
},[handleChange])
function handleMatch(){
if(Test === InputText){
console.log( &quot;a cmoplete match&quot;);
dispatch(setValue(&quot;&quot;));
return;
} 
if(Test.includes(InputText)){
console.log(&quot;good going&quot;);
return;
}
else{
console.log(Accuracy);
dispatch(setAccuracy());
return;
}
}
return (
&lt;div className=&#39;TextBox&#39;&gt;
&lt;h2&gt;Lesson 1&lt;/h2&gt;
&lt;input 
type=&quot;text&quot;
className=&#39;text-input&#39;
value={Test}
style={{backgroundColor:&quot;rgba(55,90,127,255)&quot;}}/&gt;
&lt;input 
type=&quot;Text&quot; 
className=&#39;text-input user&#39; 
onChange={handleChange}
value={InputText}
/&gt;
&lt;div className=&#39;performance&#39;&gt;
&lt;h4 className=&#39;Tags&#39;&gt;WPM:&lt;/h4&gt;
&lt;h4 className=&#39;Tags&#39;&gt;Accuracy:&lt;/h4&gt;
&lt;h4 className=&#39;Tags&#39;&gt;Average WPM:&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
)
}
export default TextBox;

答案1

得分: 0

根据TextBox.js:16上的控制台日志,似乎是在记录选定的state.Result状态,某处将状态从对象更改为数字。一旦发生这种情况,并且调用了额外的dispatch(setAccuracy());setAccuracy reducer 案例会尝试从数字的未定义属性中减去1。对非数字的数学操作往往会在最坏的情况下生成异常,在最好的情况下生成NaN

setAccuracy reducer 函数仅返回state.Accuracy - 1。Redux-Toolkit reducer 函数应该要么修改草稿状态,要么返回下一个状态...所有的状态。

示例:

const ResultSlice = createSlice({
  name: &quot;Result&quot;,
  initialState: {
    Accuracy: 100,
    WPM: 40,
    WPMAverage: []
  },
  reducers: {
    setAccuracy(state) {
      state.Accuracy = state.Accuracy - 1;
    }
  }
});

或者

const ResultSlice = createSlice({
  name: &quot;Result&quot;,
  initialState: {
    Accuracy: 100,
    WPM: 40,
    WPMAverage: []
  },
  reducers: {
    setAccuracy(state) {
      return {
        ...state,
        Accuracy: state.Accuracy - 1;
      };
    }
  }
});

第二种方法可行,但第一种方法更受欢迎,因为RTK在底层实现了immer.js,允许您编写简洁的、可变的状态更新。换句话说,它允许您编写更少的代码,更清晰、更易读和更易维护。请参阅使用 Immer 编写 Reducer

英文:

Based on the console log on TextBox.js:16, which it seems is logging the selected state.Result state that somewhere the state is mutated from an object to a number. Once this happens and an additional dispatch(setAccuracy()); is called, the setAccuracy reducer case attemps to subtract 1 from an undefined property of a number. Mathematical operations on non-numbers tend to generate exceptions at worst, and NaN at best.

The setAccuracy reducer function is only returning state.Accuracy - 1. Redux-Toolkit reducer functions should either mutate the draft state or return the next state... all of it.

Examples:

const ResultSlice = createSlice({
  name: &quot;Result&quot;,
  initialState: {
    Accuracy: 100,
    WPM: 40,
    WPMAverage: []
  },
  reducers: {
    setAccuracy(state) {
      state.Accuracy = state.Accuracy - 1;
    }
  }
});

or

const ResultSlice = createSlice({
  name: &quot;Result&quot;,
  initialState: {
    Accuracy: 100,
    WPM: 40,
    WPMAverage: []
  },
  reducers: {
    setAccuracy(state) {
      return {
        ...state,
        Accuracy: state.Accuracy - 1;
      };
    }
  }
});

The second method will work, but the first method is preferred since RTK implements immer.js under the hood and allows you to write succinct, mutable state updates. In other words, it allows you to write less code that is more clean and easier to read and maintain. See Writing Reducers with Immer.

huangapple
  • 本文由 发表于 2023年5月29日 02:02:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定