먼저 결과를 저장하는 오브젝트배열은 다음과 같다.
export interface postTestResultType{
content:string;
score:string
}
최종 데이터를 저장하는 state
const [postTestResult, setPostTestResult] = useState<postTestResultType[]>([]);
가장 먼저 정해야 할 것은 다음과 같다.
1.라디오버튼
const RadioButton = ({ value, onChange }: { value: any; onChange: any }) => {
return (
<label>
<input
type="radio"
checked={value}
onChange={onChange}
style={{ zoom: "2.0" }}
/>
</label>
);
};
2.이 라디오버튼을 감싸는 컨테이너
const RadioGroup = ({ content, i }: { content: any; i: number }) => {
const [chekedData, setCheckedData] = React.useState("");
const handleChange = (value: any, score: string) => {
setResult(content, score);
setCheckedData(value);
};
return (
<div
style={{
width: "142px",
display: "flex",
justifyContent: "space-evenly",
}}
>
<RadioButton
value={chekedData === `1`}
onChange={() => {
handleChange(`1`, "1");
}}
/>
<RadioButton
value={chekedData === `2`}
onChange={() => {
handleChange(`2`, "2");
}}
/>
<RadioButton
value={chekedData === `3`}
onChange={() => {
handleChange(`3`, "3");
}}
/>
<RadioButton
value={chekedData === `C`}
onChange={() => {
handleChange(`C`, "C");
}}
/>
</div>
);
};
map으로 10개의 리스트를 불러온다 하면 radiogroup은 10개가 생성되며, 그 안에 chekedData 에 대한 state를 선언하였으므로 체크 표시는 공유되지 않는다.
중요한 onchange 함수이다.
const handleChange = (value: any, score: string) => {
setResult(content, score);
setCheckedData(value);
};
결과를 저장하는 setResult,라디오 버튼에서 체크여부를 판단할 때 필요한
chekedData를 변경할 수 있는 setCheckedData hook
setResult는 다음과 같이 동작한다.
// 결과저장
let resultArray: postTestResultType[] = Array();
// filter함수를 위한 임시 똑같은 임시 변수
let newArray: any;
const setResult = (content: string, score: string) => {
if (resultArray.length === 0) {
resultArray.push({ content: content, score: score });
} else {
if (
resultArray.find((a) => {
return a.content === content;
})
) {
newArray = resultArray.map((a) => {
return a.content === content ? {...a,score:score} : a;
});
resultArray = [...newArray];
} else {
resultArray.push({ content: content, score: score });
}
}
console.log(resultArray);
};
처음 선택했을 때 빈 배열이라면 일단 resultArray를 push한다.
(똑같은 stack배열인데 concat을 안 한 이유는 concat은 새로운 배열을 반환하므로 return을 해줘야하기 때문에 push를 사용하였다.또한 길이를 판별하는 이유는 빈 배열일 경우에 find나 map함수가 동작하지 않는다....왜인지는 모르겠다.)
만약 기존 배열에 content가 존재한다면 filter를 사용하여 임시 배열 newArray에 map함수를 이용하여 score를 바꾼 새로운 배열을 임시저장한다. 다시 resultArray에 얕은복사(채-신 ES6문법 spread)를 한다.
아니라면 그냥 push만 해준다.
이제 이 배열을 state에 저장하자. state는 비동기적이라 setCheckedData와 동시에 setPostTestResult를 동작시켜버리면 당연히 오류가 뜬다(not iterator부터 property오류가 대표적)그러므로 useEffect훅을 사용하여
setCheckedData로 인한 리랜더링->마운트->함수 생성및 뷰 표시
에서 마운트시 setPostTestResult를 동작시키면 된다.
useEffect(() => {
setPostTestResult(resultArray);
}, [resultArray]);
마지막 파라미터를 꼭 넣어서 마운트되게 하자
-끝-