본문 바로가기
앱 개발

[react-native] 지역 선택 : select되면 함수로 state 변경해서 안내 글자 바꾸기

by evekang 2022. 6. 21.

 

 

 

앱을 처음 실행하면 지역을 선택하게끔 하려고 페이지를 작업하다가

여전히 늘 그렇듯 에러를 만났다.^^

 

구글링해보니까 input에서 입력이 되면 그 값을 가지고 오는 함수들은 많던데

정작 내가 필요한건 읍쓰..

 

 

문제점

구현하고 싶은 기능의 순서는

1. 지역을 select하지 않고 [다음] 버튼을 누른 경우 하단에 '입력이 필요합니다'라는 안내 문구를 띄운다.

2. 그 다음 지역을 select하면 invalid가 없어지면서 'OK'라는 안내 문구를 띄운다.

였는데, 

 

NativeBase의 예시 코드에는 저런 기능은 없었고...

1번 수행은 잘 하지만 그 이후 err에 담긴 state가 계속 남아있으면서 invalid에서 err을 자꾸 데려와서 이후 로직을 방해했다.

(왼) : 처음 아무것도 선택하지 않고 [다음] 버튼 클릭시                                      (우): 왼쪽 이후 인천광역시를 선택 후 [다음] 버튼 클릭시

 

제대로 선택했음에도 불구하고 invalid 가 계속 걸려서 빨갛게 표시가 되고 있다.

 

 

 

 

해결책

<Select>태그에 onValueChange를 사용해서 handleChange()함수를 실행하고,

함수 내에서 setData로 선택한 value를 담으면서 동시에 setErrors도 초기화시킨다.

 

handleChange() 함수에 setData에 value를 담고 + setErrors를 초기화시킴
<Select> 태그에 onValueChange 속성으로 handleChange()함수 실행

 

 

 

 

(왼) : 선택하지 않고 [다음] 버튼 클릭 시                                                     (오) : 왼쪽 이후 인천광역시를 선택 후 [다음] 버튼 클릭 시

 

 

 

 

전체 코드

import React, { useState } from "react";
import {
  NativeBaseProvider,
  Box,
  Center,
  Heading,
  Button,
  View,
  Text,
  Stack,
  FormControl,
  WarningOutlineIcon,
  Select,
  CheckIcon,
  HStack,
} from "native-base";

function Example() {
  const [formData, setData] = useState({});
  const [errors, setErrors] = useState({});

  const validate = () => {
    if (formData.name === undefined) {
      setErrors({ ...errors, err: "선택 안됨." });
      return false;
    } else {
      return true;
    }
  };

  const onSubmit = () => {
    validate()
      ? console.log(
          "submitted" + JSON.stringify(errors) + JSON.stringify(formData)
        )
      : console.log(
          "validation failed" +
            JSON.stringify(errors) +
            JSON.stringify(formData)
        );
  };

  const handleChange = (e) => {
    setData({ ...formData, name: e });
    setErrors({});
  };

  return (
    <Box>
      <View>
        <Heading color="emerald.400" mt="20" ml="5">
          지역<Heading>{""}을 선택하세요</Heading>
        </Heading>
      </View>
      <Stack
        space={2.5}
        alignSelf="center"
        px="4"
        safeArea
        mt="4"
        w={{
          base: "100%",
          md: "25%",
        }}
      >
        <Center>
          <FormControl isRequired isInvalid={"err" in errors}>
            <FormControl.Label _text={{ bold: true }}>
              시를 선택하세요
            </FormControl.Label>
            <Select
              minWidth="200"
              accessibilityLabel="Choose Service"
              placeholder="선택"
              _selectedItem={{
                bg: "teal.600",
                endIcon: <CheckIcon size={5} />,
              }}
              mt="1"
              onValueChange={(e) => handleChange(e)}
            >
              <Select.Item label="서울특별시" value="서울" />
              <Select.Item label="부산광역시" value="부산" />
              <Select.Item label="대구광역시" value="대구" />
              <Select.Item label="인천광역시" value="인천" />
              <Select.Item label="광주광역시" value="광주" />
              <Select.Item label="대전광역시" value="대전" />
              <Select.Item label="울산광역시" value="울산" />
              <Select.Item label="세종특별시" value="세종" />
            </Select>
            {"name" in formData ? (
              <HStack space={2}>
                <CheckIcon size="5" mt="0.5" color="emerald.500" />
                <Text fontSize="xs">OK</Text>
              </HStack>
            ) : "err" in errors ? (
              <FormControl.ErrorMessage
                leftIcon={<WarningOutlineIcon size="xs" />}
              >
                입력이 필요합니다.
              </FormControl.ErrorMessage>
            ) : (
              <HStack space={2}>
                <Text fontSize="xs"></Text>
              </HStack>
            )}
          </FormControl>
          <Button
            _pressed={{ bg: "red.500" }}
            mt="10"
            mx="100"
            onPress={onSubmit}
          >
            다음
          </Button>
        </Center>
      </Stack>
    </Box>
  );
}

export default function Index({ navigation }) {
  navigation.setOptions({
    headerShown: false,
  });

  return (
    <NativeBaseProvider>
      <Box>
        <Example />
      </Box>
    </NativeBaseProvider>
  );
}

 

 

완성된 기능

 

 

 

 

 

 

 

하 개운행

반응형

댓글