본문 바로가기

TIL

[TIL-165] React Native

ScrollView에서 아래로 당겨 새로고침하기

RefreshControl

ScrollView에는 refreshControl이라는 prop이 있다.

 

 

뒤로가기 새로고침

RefreshControl을 이용하여 사용자가 원할 때 화면을 새로고침하는 것도 좋지만, 뒤로가기로 화면이 이동되었을 때 lifecycle이 실행되지 않는 것이 문제의 원인이었다. 이 문제는 네비게이팅하는 데 사용하고 있는 "react-navigation/native" 라이브러리에서 제공하는 useIsFocused 훅으로 해결할 수 있다.

 

import {useIsFocused} from '@react-navigation/native';

const Home = ({navigation}) => {
  const isFocused = useIsFocused();

  useEffect(() => {
    if (token.access) {
      getPoint(token.access);
    } else {
      alert('잘못된 로그인입니다.');
      navigation.navigate('Login');
    }
  }, [isFocused]);

};

화면이 최초 렌더링될 때, 리덕스 저장소에서 token을 가져와 사용자의 point를 조회하는 요청을 보내는 useEffect가 있었다. 여기에 두번째 인자로 오는 의존성 배열이 비어있었는데, isFocused를 넣어서 뒤로가기를 포함한 화면 이동이 일어났을 때도 이 코드가 실행되게 했다.

 

 

 

 

모달창이 켜질 때, <Modal> 컴포넌트 안의 <TextInput> focus

useRef를 사용하여 focus()하기

  useEffect(() => {
    if (isModal) {
      senderInput.current.focus();
  //  senderInput.current.selection = {
  //    start: sender.length,
  //    end: sender.length,
  //  };
    }
  }, [isModal]);
  
  ...
  
  <TextInput
    value={sender}
    onChangeText={text => {
      setSender(text);
    }}
    ref={senderInput}
  />

useRef를 이용하여 <TextInput> 컴포넌트에 senderInput으로 ref를 주고, "isModal" state의 값이 true로 바뀌어 모달이 켜질 때 focus() 메서드를 실행하여 포커스시키게 했다.

TextInput에 포커스는 되는데 문제가 있다. 1) 커서가 맨 앞에 뜨고, 2) 키보드가 뜨지 않는다. 키보드의 경우, 처음엔 떴는데 이제 안 뜬다.

 

<Modal
    transparent
    visible={isModal}
    onShow={() => {
      senderInput.current.focus();
      senderInput.current.selection = {
        start: sender.length,
        end: sender.length,
      };
}}>

다른 건 다 그대로 두고, useEffect 안에서 동작시킨 코드를 <Modal>의 "onShow" prop의 함수에서 실행해봤더니 키보드가 뜬다. 다른 곳에서 해결책으로 모달이 켜질 때 setTimeOut으로 딜레이를 걸라는 얘기가 있는 걸 봐서는, 모달이 켜지는 속도와 상관이 있는 모양이다.

 

하지만 여전히 커서 위치가 이상하다. 커서를 옮기기 위해 selection 속성을 이용해봤지만, selection 값이 바뀌어도 커서는 계속 맨 앞에 있었다. 그리고 input의 text를 편집해서 커서의 위치가 바뀌어도 selection 값은 바뀌지 않는다. selection은 커서랑 관련이 없는 건가... 공식문서에서 "Set start and end to the same value to position the cursor."라고 했는데 이상하다.

 

onSelectionChange={e => {
  console.log(e.nativeEvent.selection);
}}
onFocus={e => {
  e.target.selection = {
    start: sender.length,
    end: sender.length,
  };
  console.log(e.target);
}}

<TextInput>에 onSelectionChange가 일어날 때마다 selection을 콘솔로 찍어보니 커서의 위치가 바뀌면 값이 바뀐다. 그래서  onFocus 되었을때 selection 값을 맨 마지막 위치로 부여해보았는데 마찬가지로 커서는 text의 시작점에 있다.

 

const [selection, setSelection] = useState({
  start: sender.length,
  end: sender.length,
});
  
...

selection={selection}
onSelectionChange={e => {
  console.log(e.nativeEvent.selection);
  setSelection(e.nativeEvent.selection);
}}

state를 사용해서 selection을 부여하는 방법도 써봤다. 커서의 이동에 따라 selection의 값은 잘 바뀌지만 최초에 설정해둔 selection에 따라 커서가 위치하지는 않는다.

 

 

<TextInput> autoFocus

<TextInput
    value={sender}
    onChangeText={text => {
      setSender(text);
    }}
    autoFocus={true}
/>

useRef 없이, TextInput 자체에 autoFocus라는 prop를 이용해서 포커스해보았다. 공식문서에 따르면, autoFocus를 true로 해두었을 때 "focuses the input on componentDidMount or useEffect." 된다. 따라서 이 상황에서는 <Modal> 컴포넌트가 활성화되면서 그 안의 <TextInput>도 마운트될 때, 자동으로 <TextInput>이 포커스된다. useRef를 사용하는 방법보다 간편하지만 ,무엇보다 커서가 깔끔하게 가장 오른쪽에 뜬다.

 

하지만 autoFocus될 때 키보드가 뜨지 않는 문제가 여전히 있다. 안드로이드라서 그런 것 같기도 하다. Stack Navigation의 문제라는 이야기도 보았다.

 

autoFocus랑 useRef 사용한 focus()를 동시에 적용해보기도 했는데 그럼 autoFocus가 적용되는지 키보드가 뜨지 않았다.

 

 

공부할 것

  • setTimeout

'TIL' 카테고리의 다른 글

[TIL-167] React Native  (0) 2022.04.15
[TIL-166] React Native  (0) 2022.04.14
[TIL-164] React Native  (0) 2022.04.12
[TIL-163] React Native  (0) 2022.04.11
[TIL-162] 노마드코더 React Native #2.0~#  (0) 2022.04.09