작성
·
192
0
장고에서는 별다른 에러는 없는데 위 내용은 장고에서 username을 불러오지 못한다는 의미인걸까요..?
답변 2
1
안녕하세요.
이는 JS 에서 undefined 으로부터 username 이름의 속성을 참조했기 때문에 TypeError가 발생했다는 오류입니다.
Login.js에서 실습을 하셨다면 Form 컴포넌트에 onFinish 속성값으로 onFinish 함수를 콜백으로 지정하셨을 텐데요. 이때 form submit이 이뤄질 때 onFinish 함수가 호출이 되고 인자로 form fields 값들이 넘어옵니다.
현재 Login.js 의 42번째 라인의 코드가 무엇인가요? 만약 const { username, password } = values; 라면, values이 각 필드값이 들어있는 object여야하는데 undefined라는 것은 현재 리액트 구현에 뭔가 문제가 있다는 것입니다.
혹시 속성값 지정 시에 onFinish={onFinish} 가 아니라 onFinish={onFinish()} 로 구현하신 것은 아닌가요?
코드를 차근차근 확인해보시며 정리해보시고나서, 다시 질문 부탁드립니다.
화이팅입니다. :-)
0
안녕하세요 강사님 질문올린 후에 다시한번 코드를 수정해서 테스트 해봤는데 이번엔
어떤 오류도 발생하지 않고 새로고침만 실행 됬습니다.
export default function Login() {
const {dispatch} = useAppContext()
const location = useLocation();
const history = useHistory();
const [errors, setErrors] = useState({});
// const [inputs, setInputs] = useState({});
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const [loading, setLoading] = useState(false);
const [formDisabled, setFormDisabled] = useState(false)
const {from: loginRedirectUrl} = location.state || {
from: {pathname : "/"}
}
const onSubmit = () => {
// e.preventDefault()
setErrors({});
const data = {username, password}
axiosInstance.post("/accounts/token/", data)
.then(response => {
const {
data : {
token: jwtToken,
}
} = response
dispatch(setToken(jwtToken))
history.push(loginRedirectUrl)
})
.catch(error => {
if (error.response) {
setErrors({
username: (error.response.data.username || []).join(""),
password: (error.response.data.password || []).join(""),
});
console.log('데이터 수신불가')
console.log(error.response)
history.go()
}
})
.finally(() => {
setLoading(true)
});
};
useEffect(() => {
const isEnable= Object.values(username).every(s => s.length > 0);
setFormDisabled(!isEnable)
}, [username])
const onUsernameChange = (e) => {
setUsername(e.target.value)
}
const onPasswordChange = (e) => {
setPassword(e.target.value)
}
return (
<div className="app">
{/* Start Header */}
<div className="header">
<div className="logo">
<LogoBox/>
</div>
<div className="search-bar">
<SearchBox/>
</div>
<div className="top-nav-bar">
<AccountMenu />
</div>
</div>
{/* End Header */}
<div className="signup">
<Paper
sx={{
height: '600px',
width: '56%',
marginLeft: 28,
alignItems: 'center'
}}
elevation={9}
>
<form onSubmit={onSubmit}>
<Stack alignItems={'center'} margin={10} spacing={3} >
<TextField
id="outlined-username-input"
label="Username"
type="username"
autoComplete="current-username"
name="username"
onChange={onUsernameChange}
sx={{ m: 1, width: '50ch' }}
InputProps={{
startAdornment : (
<InputAdornment position="start">
<AccountCircle />
</InputAdornment>
)
}}
/>
{errors.username}
<TextField
id="outlined-password-input"
label="Password"
type="password"
autoComplete="current-password"
name="password"
onChange={onPasswordChange}
sx={{ m: 1, width: '50ch' }}
InputProps={{
startAdornment : (
<InputAdornment position="start">
<PasswordIcon />
</InputAdornment>
)
}}
/>
{errors.password}
<Button
type="submit"
value="로그인"
disabled={loading || formDisabled}
variant="contained"
fullWidth
>
Login
</Button>
<Button
href="/accounts/signup/"
value="회원가입"
variant="contained"
fullWidth
>
Sign Up
</Button>
</Stack>
</form>
</Paper>
</div>
로컬해서 테스트할 떄는 정상적으로 작동하는데.... 혹시 프론트는 로컬과 클라우드로 올릴때
코드가 다르게 적용되는 부분이 있나요? 위 코드는 Material UI 프레임워크를 사용해서 테스트하여
onFinish가 아닌 onSubmit으로 구현하였습니다.
안녕하세요.
페이지가 새로고침이 된 것이 아니라, form 기본의 submit이 동작을 한 듯 하구요. <form>에 action지정이 없으니 현재 페이지로 submit이 동작을 하여 새로고침이 된 듯한 효과가 발생한 듯 합니다.
유형주 님께서는 <form> 의 기본 submit 동작을 수행하지 않고, 직접 구현하신 로직을 onSubmit을 통해 수행하실려는 것이잖아요. 그렇다면 form onSubmit에 지정된 onSubmit 함수에서 e.preventDefault()를 호출하거나 return false;를 해주셔야 합니다.
보여주신 코드에서는 e.preventDefault(); 를 호출하셨지만 주석처리를 하셨더라구요. e 객체는 onSubmit 함수의 첫번째 인자로 지정이 됩니다. 인자에서 e 객체를 받아서 호출해주시면 적어도 말씀하신 페이지가 새로고침이 되는 듯한 증상이 없어지지 않을까 싶습니다.
조급하게 생각하지 마시고, 차근차근 정리해보며 문제를 풀어가보세요. 이 모든 것이 하나 하나 쌓여 경험이 되는 것입니다.
화이팅입니다. :-)