Study/React

[React][코딩온] Redux 이용해서 평균, 표준편차, 상대표준편차 상태관리하기

다니니니 2024. 8. 20. 23:16
728x90

 

이 포스팅에서 이어짐(https://daddda3232.tistory.com/77)

 

 

 

Redux 배운 김에 연습할 겸 리덕스를 이용해서 input에 값들을 입력하면 이에 대한 평균, 표준편차, 상대표준편차를 구하기로함

원래 기존에 useState 쓰던걸 리팩토링함

 

 

우선 이런식으로 먼저 여섯개의 input을 만들어줬다.

저 input에 숫자를 입력하고 focus가 빠져나가면 평균, 표준편차, RSD가 계산되는 식으로 할 것

(그래서 onBlur 이벤트 사용함)

 

우선 컴포넌트는 아래와 같이 만들었는데,

input에 값을 입력하는 <StandardPeak /> 컴포넌트와

이에 따른 결과값이 출력되는 <StandardResult /> 를 만들었음

 

import './App.css';
import React, {useMemo, useState} from 'react';
import StandardPeak from './components/StandardPeak';
import StandardResult from './components/StandardResult';

function App() {

  return (
    <div className="App">
      <StandardPeak/>
      <StandardResult/>
    </div>
  );
}

export default App;

 <StandardPeak /> 컴포넌트 

여기다가 onBlur 이벤트 걸어주고 이벤트가 발생하면 호출되는 콜백함수에

인풋값들을 담을 배열, 이 배열값들을 바탕으로 평균, 표준편차, RSD 들을 구할 함수를 호출해줌

import React, {useRef} from 'react'
import { useDispatch, useSelector } from 'react-redux';
import { peakArr, stdAvg, stdSD, stdRSD } from '../store/stdValueSlice';

export default function StandardPeak() {
    const inputRef = useRef([])
    const stdArr = useSelector(state => state.stdValue.stdArr)
    const dispatch = useDispatch();

    const inputArr = [1,2,3,4,5,6]

    const addPeakRes = (e, idx) => {
      const res = Number(e.target.value);
      const peak = stdArr.map((v,i) => {
        if(i === idx) return res;
        else return v;
      })
      
      dispatch(peakArr(peak))
      dispatch(stdAvg())   
      dispatch(stdSD())   
      dispatch(stdRSD())   
    }

  return (
    <div>
      {
        inputArr.map((number) => 
          <input key={number} type='number' id={'std'+(number)} 
        ref={el => inputRef.current[number - 1] = el} onBlur={(e)=>addPeakRes(e, number-1)}/>
        )
      }
    </div>
  )
}

<StandardResult /> 컴포넌트

여기는 단순히 결과만 나옴

나중에 적합/부적합 여부도 표시할 예정

import React from 'react'
import { useDispatch, useSelector } from 'react-redux';

export default function StandardResult() {
  const { stdAvg, stdSD, stdRSD } = useSelector(state => state.stdValue)
  console.log(stdAvg, stdSD, stdRSD);
  

  return (
    <div>
        <input type='number' id='stdAvg' placeholder='평균' readOnly value={stdAvg > 0? stdAvg : ''}/>
        <input type='number' id='stdSD' placeholder='표준편차' readOnly value={stdSD > 0? stdSD : ''}/>
        <input type='number' id='stdRSD' placeholder='RSD' readOnly value={stdRSD > 0?  stdRSD : ''}/>
    </div>
  )
}

 

Redux store

여기서 이제 상태관리를 하게 되는데 

여기서 평균, 표준편차, RSD 를 계산하는 로직을 작성함 

코드를 간단하게 하기 위해서 배열 메서드 중 reduce를 사용했다.

평균은 그냥 반올림하고 표준편차와 상대표준편차는 소수점 2자리까지 표시함

평균은 그럭저럭 해냈는데 표준편차 구하기가 좀 어려워서 챗지피티의 도움을 좀 받았다.. 

import { createSlice } from '@reduxjs/toolkit'

// 평균을 구하는 함수
const calculateAverage = (arr) => arr.reduce((acc, num) => acc + num, 0) / arr.length;

// 표본 표준편차를 구하는 함수
const calculateSampleStandardDeviation = (arr) => {
    const avg = calculateAverage(arr);
    const variance = arr.reduce((acc, num) => acc + Math.pow(num - avg, 2), 0) / (arr.length - 1);
    return Math.sqrt(variance);
};

const stdValueSlice = createSlice({
    name : 'standard',
    initialState : {stdArr : [0,0,0,0,0,0], stdAvg : 0, stdSD : 0, stdRSD : 0},
    reducers : {
        peakArr : (state, action) => {state.stdArr = action.payload},
        stdAvg : (state, action) => {
            state.stdAvg = Math.round(calculateAverage(state.stdArr))
        },
        stdSD : (state, action) => {
            state.stdSD = Math.round(calculateSampleStandardDeviation(state.stdArr) * 100) / 100
            
        },
        stdRSD : (state, action) => {
            state.stdRSD = Math.round(((state.stdSD / state.stdAvg)*100)*100) / 100
        }
    }
})

export const { peakArr, stdAvg, stdSD, stdRSD } = stdValueSlice.actions;

export default stdValueSlice.reducer;

 

결과

엑셀이랑 내가 만든 리액트앱이랑 출력되는 값 비교

 

엑셀

 

리액트 앱

일단 값이 일치하게 나왔음!!

 

 

지금 이 방법이 맞는 방법인지는 모르겠지만 이전에 단순히 useState 를 사용할 때 보다 상태관리가 더 편해진 것 같다.

앞으로 더 구현내용이 늘어나면 어떻게 될지는 모르겠지만..

일단 표준액들의 결과에 대한 값들을 얻어서 기쁘다! 이제 검액들 결과 넣고 적합/부적합 기능도 넣으면 될듯!

zustand를 겉핥기로 공부해봤는데 걔가 더 쉬운거 같음.. 일단 redux이용해서 만들어보고 zustand로도 리팩토링해봐야지

 

728x90