Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

JustDoEat

[React/오류해결] 서버로 데이터 전송시 상태변화가 안되는 문제(Date객체 <=> 문자열 변환과정에서) 본문

카테고리 없음

[React/오류해결] 서버로 데이터 전송시 상태변화가 안되는 문제(Date객체 <=> 문자열 변환과정에서)

kingmusung 2024. 7. 6. 03:16

개요.

https://github.com/2024-EveryCare

 

2024-EveryCare

2024-EveryCare has 2 repositories available. Follow their code on GitHub.

github.com

 

1.OCR인식 데이터를 받아 화면에 랜더링 하는 과정.

2.OCR데이터가 인식이 잘 안 되는 경우 null값으로 들어옴 -> 사용자가 수기로 입력.

 

위 두가지 경우의 수가 존재하는데. 각 과정에서 문자열 <=> Date객체로 변환하는 과정 중에 생긴 오류

 

첫 번째 문제점

  • OCR인식 성공 시 서버에서 주는 날짜 값은 문자열형식(24-12-01) 하지만 프런트에서 받아야 하는 데이터 형식은 Date 객체
  • OCR인식 실패시 사용자가 수기로 입력하는 값은 Date객체 형식, 즉 두 개의 경우에 수에 대해 대처를 모두 해야 함.

(위는 문자열 형식의 Date값 아래는 Date객체 형식의 Date값)

 

(새로 파일을 만든 후 input태그의 value값을 확인해 보니 이건 또 문자열 형식으로 나왔다..)

 

문제해결.

  • 날짜입력 폼으로 DatePicker를 사용하는 상황, datepicker는 input태그처럼 value prop이 아닌 selected={값} 으로 selected prop을 받음.(selected 내부에는 Date객체가 들어가야 오류가 안 나옴) -> 조사 후 조치

=> useEffect를 사용 페이지가 랜더링이 될 때 시작일과, 종료일을 저장하는 useState 배열을 업데이트하기 전에, 서버에서 넘어온 문자열 타입의 날짜를 

페이지 랜더링이 될때 useEffect를 이용하여 해당 함수를 실행 후 저장.

const formatStartDate = (formatedDate) => {
    const date = new Date(formatedDate);
    setStartDate(date);
  };

 

Date 객체로 넘겨준 후 저장.

 

  • (부가) 데이터 타입으로 인한 오류 해결
const [startDate, setStartDate] = useState<string | Date | null>(null);
const [endDate, setEndDate] = useState<string | Date | null>(null);

useState배열에 허용하는 데이터 타입으로 인한 오류

const [startDate, setStartDate] = useState<string | null>(null);
const [endDate, setEndDate] = useState<string | null>(null);

 

Date타입을 뺀 후 Date타입을 String으로 변환 후 넣어주는 식으로 통일함.


두 번째 문제점.(날 괴롭힌 주범.)

  • OCR이 날짜 인식을 성공을 했다면 문자열 => Date객체로 변환 후 성공적으로 랜더링이 되었을 것.
  • 반대로 OCR이 날짜 인식을 실패해서 사용자가 입력을 한다면 Date객체 => 문자열 변환 후 서버에 넘겨주면 됨.
  • 여기서 문제점! 최종 데이터(날짜값)가 서버로 데이터를 넘겨줄 때(저장하기) 변경된 값이 반영이 되지 않음.

(API테스트를 위한 장고서버, 날짜가 지금 보면 Date객체로 찍히는데 분명 프론트코드에서 문자열로 만들어주었다.)

 

문제해결.

  • console.log 도배 + 날짜값에 useEffect적용 후 console.log찍어보기

 

아~~! 서버로 전송이 완료가 되고 상태가 뒤늦게 변경이 되는 점을 확인을 했다.

 

확인되면 뭐 하나... 고민이 더 생겨버렸는걸..

 

날짜값의 useEffect로직 밑에 서버로 전송하는 로직을 짜볼까?

=> 사용자가 날짜를 바꿀 때마다 서버에 전송을 할 수 없잖아.. 그러므로 기각..

=> 그 외에 질병, 병원, 복약사이클도 변경이 되었을 때  추후에 위와 같은 문제에 직면되어서 변경된 값이 전송이 안되면 어쩌지?..

 

꼬리에 꼬리를 무는 무수한 고민 끝내 해결책을 찾았다.. 이놈...

 

 

"상태 업데이트가 비동기적으로 처리되기 때문에, 상태가 완전히 업데이트되기 전에 서버로 데이터를 전송하는 문제가 발생할 수 있습니다. 특히, 상태 업데이트 함수는 즉시 변경 사항을 적용하지 않고, 다음 렌더링 주기에서 상태를 업데이트합니다."

 

=> 다음 렌더링 주기에서 상태가 업데이트가 된다면 저장하기 버튼에 useState로 상태값을 넣은 후 useEffect를 걸어주고, "저장하기" 버튼을 누르면 렌더링이 다시 일어나면서 상태값이 업데이트가 되고, 그 값이 서버로 가겠구나!

(유레카 100번 외침 끝에 시도를 한 결과)

 

useEffect(() => {
    console.log('동작 중....', startDate);
    console.log('동작 중....', endDate);

    if (dataSubmit) {
      const drugCode = saveMediData.map((item) => item.drugCode);
      axios
        .put('http://127.0.0.1:8000/test/', {
          drugCode: drugCode,
          intakeStart: startDate,
          intakeEnd: endDate,
          intakeCycle: intakeCycle,
          intakeDaily: intakeDaily,
          hospital: hospital,
          disease: disease,
        })
        .then((response) => {
          console.log('서버 응답:', response.data);
        });
    }
  }, [
    dataSubmit,
    disease,
    endDate,
    hospital,
    intakeCycle,
    intakeDaily,
    saveMediData,
    startDate,
  ]);

 

  • dataSubmit 을 boolean 값으로 만든 후 저장하기 버튼이 눌리면 true로 바뀌게 만듦.
  • disease, hospital등등 페이지에서 입력받아야 하는 값들이 변경이 될 때마다 useEffect가 실행이 되겠지만 저장하기 버튼이 아직 안 눌렸으므로 전송은 안 됨
    => 값의 변화가 있을 때마다 useEffect가 쓰인다는 게 최적화 측면에서 안 좋을 거 같다는 생각을 많이 하긴 했다..)
  • 저장하기 누르기 전에 이전 모든 값들은 상태변화가 돼있으나. 다음 렌더링 주기에 완료가 되므로, 최종적으로 저장하기를 누르면 dataSubmit값이 바뀌면서 렌더링이 일어날 것이다. 그 후 재렌더링이 되면서 제대로 바뀐 값들이 서버로 전송이 될 것이다.