Mobile/react-native

[react-native] typescript 환경에서 Hooks 예제

춘햄 2024. 2. 20. 09:13

 좀 더 typescript와 친해져보자. 

 

기존에 자주 사용하는 Hook들을 ts를 사용하여 변경하는 예제들을 확인하려고 한다.


- useState

import React, {useState} from 'react';
import {Button, Text, TextInput, View} from 'react-native';

const MessageForm = () => {
  // string 타입
  const [text, setText] = useState<string>('');
  // interface 타입 체크 or null
  const [lastMessage, setLastMessage] = useState<{
    message: string;
    date: Date;
  } | null>(null);

  const onPress = () => {
    setLastMessage({
      message: text,
      date: new Date(),
    });
    setText('');
  };

  return (
    <View>
      <TextInput value={text} onChangeText={setText} />
      <Button title="PRESS ME" onPress={onPress} />
      {lastMessage && (
        <View>
          <Text>
            마지막 메시지: {lastMessage.message} (
            {lastMessage.date.toLocaleString()})
          </Text>
        </View>
      )}
    </View>
  );
};

export default MessageForm;

 

- useRef

import React, {useEffect, useRef, useState} from 'react';
import {Button, Text, TextInput, View} from 'react-native';

const MessageForm = () => {
  const [text, setText] = useState<string>('');
  const [lastMessage, setLastMessage] = useState<{
    message: string;
    date: Date;
    id: number;
  } | null>(null);
  const nextId = useRef<number>(1);
  /* 렌더링될 때는 null, 한번 렌더링된 뒤에는 TextInput의 인스턴스가 담긴다.
   * 이런 상황에서는 반드시 Generic을 사용한다.
   *  */
  const inputRef = useRef<TextInput | null>(null);

  const onPress = () => {
    setLastMessage({
      message: text,
      date: new Date(),
      id: nextId.current,
    });
    setText('');
    nextId.current += 1;
  };

  useEffect(() => {
    if (!inputRef.current) {
      return;
    }
    inputRef.current.focus();
  }, []);

  return (
    <View>
      <TextInput value={text} onChangeText={setText} ref={inputRef} />
      <Button title="PRESS ME" onPress={onPress} />
      {lastMessage && (
        <View>
          <Text>
            마지막 메시지: {lastMessage.message} (
            {lastMessage.date.toLocaleString()})
          </Text>
        </View>
      )}
    </View>
  );
};

export default MessageForm;

 

- useReducer

import React, {useReducer} from 'react';
import {Button, Text, View} from 'react-native';

interface CounterState {
  value: number;
}

const initialState: CounterState = {
  value: 1,
};

type CounterAction = {type: 'increment'} | {type: 'decrement'; by: number};

const reducer = (state: CounterState, action: CounterAction) => {
  switch (action.type) {
    case 'increment':
      return {
        value: state.value + 1,
      };
    case 'decrement':
      return {
        value: state.value - action.by,
      };
    default:
    throw new Error('Unhadled action type');
  }
};

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <View>
      <Text>{state.value}</Text>
      <Button title="+1" onPress={() => dispatch({type: 'increment'})} />
      <Button
        title="-1"
        onPress={() => dispatch({type: 'decrement', by: -1})}
      />
    </View>
  );
};

export default Counter;