0Pricing
React Native Academy · 강의

컴포넌트에서 저장소 상태 읽고 업데이트하기

useStore 훅을 사용해 React Native 컴포넌트에서 저장소 값과 동작에 접근하고, 버튼 누르기 또는 양식 제출로 업데이트를 실행합니다.

컴포넌트에서 저장소 상태 읽고 업데이트하기은(는) CoddyKit의 무료 React Native Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Native Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Connecting a Component to Zustand

Using a Zustand store in a component is as simple as calling the store hook at the top of the function. The hook is the same object returned by create. You can pass a selector to pick specific values, or read actions directly. No import of useSelector or useDispatch is required — the store hook handles everything.

import { useCounterStore } from '../stores/counterStore';

export default function CounterScreen() {
  const count = useCounterStore((state) => state.count);
  const increment = useCounterStore((state) => state.increment);
  const decrement = useCounterStore((state) => state.decrement);

  return (
    <View style={styles.container}>
      <Text style={styles.count}>{count}</Text>
      <Button title='Increment' onPress={increment} />
      <Button title='Decrement' onPress={decrement} />
    </View>
  );
}

Selecting Multiple Values Efficiently

To read multiple values from a Zustand store without causing excessive re-renders, you have two options. You can call the store hook multiple times with individual selectors (each subscription is independent), or you can return an object and use the shallow equality helper to compare each property separately.

import { shallow } from 'zustand/shallow';

// Option 1: multiple hooks (preferred for 2-3 values)
const count = useCounterStore((s) => s.count);
const status = useCounterStore((s) => s.status);

// Option 2: shallow equality for multiple values at once
const { count, status } = useCounterStore(
  (s) => ({ count: s.count, status: s.status }),
  shallow
);

Triggering Updates from Button Presses

Zustand actions are plain JavaScript functions, so you pass them directly to React Native event handlers like onPress. You do not need to dispatch an action object or call a helper — just call the function. This makes the component code cleaner and easier to read compared to the Redux dispatch pattern.

export default function TodoInput() {
  const [text, setText] = React.useState('');
  const addTodo = useTodoStore((state) => state.addTodo);

  const handleAdd = () => {
    if (text.trim()) {
      addTodo(text.trim());
      setText('');
    }
  };

  return (
    <View>
      <TextInput value={text} onChangeText={setText} placeholder='New todo' />
      <Button title='Add' onPress={handleAdd} />
    </View>
  );
}

Reading Store State in a FlatList

Zustand stores work naturally with React Native's FlatList. Select the array from the store and pass it to the data prop. Zustand only re-renders this component when the array reference changes, which happens when your store action replaces or mutates the items array and returns a new reference via set.

export default function TodoList() {
  const todos = useTodoStore((state) => state.todos);
  const removeTodo = useTodoStore((state) => state.removeTodo);

  return (
    <FlatList
      data={todos}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <TouchableOpacity onPress={() => removeTodo(item.id)}>
          <Text>{item.text}</Text>
        </TouchableOpacity>
      )}
    />
  );
}

Updating Nested State

When your store state has nested objects, pass a function to set and spread the nested level you want to update. Without spreading, set would replace the top-level key entirely, wiping out other nested properties. Alternatively, use the Immer middleware (covered in the previous lesson) to mutate nested values directly.

export const useProfileStore = create<ProfileStore>((set) => ({
  profile: {
    name: '',
    bio: '',
    avatar: null,
  },
  updateName: (name: string) =>
    set((state) => ({ profile: { ...state.profile, name } })),
  updateBio: (bio: string) =>
    set((state) => ({ profile: { ...state.profile, bio } })),
}));

Optimistic UI Updates

Optimistic updates improve perceived performance by updating the UI immediately when the user takes an action, before waiting for the server response. In Zustand, call set to update state immediately, then make the API call. If the API fails, call set again to revert the state to its previous value.

toggleLike: async (postId: string) => {
  // Update UI immediately
  set((state) => ({
    posts: state.posts.map((p) =>
      p.id === postId ? { ...p, liked: !p.liked } : p
    ),
  }));
  try {
    await api.toggleLike(postId);
  } catch {
    // Revert on failure
    set((state) => ({
      posts: state.posts.map((p) =>
        p.id === postId ? { ...p, liked: !p.liked } : p
      ),
    }));
  }
}

Resetting Store State

A common pattern is to add a reset action that restores the store to its initial state. Store the initial state in a constant outside the create call and reference it in the reset action. This is useful for logout flows where you need to clear all user data from every store at once.

const initialState = { user: null, token: null, isLoggedIn: false };

export const useAuthStore = create<AuthStore>((set) => ({
  ...initialState,
  login: (user, token) => set({ user, token, isLoggedIn: true }),
  logout: () => set(initialState), // restore all fields to initial values
}));

Watching Store Changes with subscribe

useStore.subscribe lets you react to store changes outside of React components — for example, writing to AsyncStorage whenever settings change, or logging analytics events when specific state transitions occur. Always unsubscribe in the cleanup function to avoid memory leaks.

useEffect(() => {
  const unsubscribe = useSettingsStore.subscribe(
    (state) => state.theme,
    (theme) => {
      console.log('Theme changed to:', theme);
      AsyncStorage.setItem('theme', theme);
    }
  );
  return unsubscribe; // cleanup on unmount
}, []);

Sharing State Between Screens

Because Zustand stores live outside any component tree, they are perfect for sharing state between screens without prop drilling or React Navigation params. Screen A updates the store, Screen B reads from it — both see the same live state immediately. This is much simpler than passing data through route params for deep navigation hierarchies.

// ScreenA.tsx — writes to store
const setSelectedProduct = useProductStore((s) => s.setSelected);
<Button title='View Details' onPress={() => {
  setSelectedProduct(product);
  navigation.navigate('ProductDetail');
}} />

// ScreenB.tsx — reads from store
const product = useProductStore((s) => s.selected);

Testing Zustand Store Actions

Testing a Zustand store is straightforward because it has no dependencies on React. Import the store, call actions directly on getState(), and assert the updated values. You can also reset the store between tests by calling the reset action or overwriting state with setState to ensure test isolation.

import { useCounterStore } from '../counterStore';

before Each(() => {
  useCounterStore.getState().reset();
});

test('increment increases count by 1', () => {
  useCounterStore.getState().increment();
  expect(useCounterStore.getState().count).toBe(1);
});

test('reset brings count back to 0', () => {
  useCounterStore.setState({ count: 5 });
  useCounterStore.getState().reset();
  expect(useCounterStore.getState().count).toBe(0);
});

Form State with Zustand

Zustand can manage form state that needs to be shared between multiple screens in a multi-step form flow. Store field values and a current step number in the store, and let each screen read and update only its own fields. On final submission, access the complete form data from getState() in the submit handler.

export const useFormStore = create<FormStore>((set) => ({
  step: 1,
  name: '',
  email: '',
  password: '',
  setField: (field, value) => set({ [field]: value }),
  nextStep: () => set((state) => ({ step: state.step + 1 })),
  reset: () => set({ step: 1, name: '', email: '', password: '' }),
}));

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: calling the store hook with a selector efficiently subscribes a component to only the state it needs, Zustand actions are plain functions that you pass directly to event handlers, and store.subscribe enables side effects like caching or analytics outside the React lifecycle. Next up we explore persisting Zustand state with AsyncStorage.

자주 묻는 질문

“컴포넌트에서 저장소 상태 읽고 업데이트하기” 강의는 무료인가요?

네 — “컴포넌트에서 저장소 상태 읽고 업데이트하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Native Academy 강의 전체를 잠금 해제할 수 있습니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“컴포넌트에서 저장소 상태 읽고 업데이트하기”에서 뭘 배우나요?

useStore 훅을 사용해 React Native 컴포넌트에서 저장소 값과 동작에 접근하고, 버튼 누르기 또는 양식 제출로 업데이트를 실행합니다. 브라우저에서 직접 실행하는 실습 코드로 React Native Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

React Native Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 React Native Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“컴포넌트에서 저장소 상태 읽고 업데이트하기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 React Native Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 React Native Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Zustand 저장소 만들기
  2. 컴포넌트에서 저장소 상태 읽고 업데이트하기
  3. AsyncStorage로 Zustand 상태 유지하기
  4. 슬라이스 패턴과 Devtools 통합
← React Native Academy(으)로 돌아가기