cp716716
@cp716716

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【React Native + Expo】useContextとuseReducerの利用方法について①

Qiita初心者です。
誤字脱字、至らない点があるかもしれませんがよろしくお願いします。

解決したいこと

React Native + Expoでアプリをつくっています。
hooksのuseContextとuseReducerを使用し
グローバルな値をどのコンポーネントでも更新ができるようにしたいです。

親コンポーネントにまとめて必要な処理を記述する方法ではうまくいきましたが、
親コンポーネントが膨大な記述になるので、
別ファイル内でグローバルなデータの状態管理をしたいのです。

しかし、以下エラーが表示されてしまい、うまくいきません。

React Nativeも初心者なもので、
解決策についてご教示いただけましたら幸いです。

以下を参考にさせていただきました。
(5 Context用のコンポーネントを作成)
https://reffect.co.jp/react/react-usecontext-understanding#Context

IMG_3411 2.PNG

スクリーンショット 2022-12-16 16.02.05.png

該当するソースコード

【階層】
スクリーンショット 2022-12-16 17.14.56.png

【親コンポーネント】

TestScreen.jsx
import React from 'react';
import { View, Text } from 'react-native';

import TestComponent from '../components/TestComponent';
import { CountProvider } from '../context/TestContext';

export default function TestScreen() {
    
    return (
        <CountProvider>
        <View>
            <Text>
                親コンポーネントのテキスト
            </Text>
            < TestComponent />
        </View>
        </CountProvider>
    );
}

【子コンポーネント】

TestComponent.jsx
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { useCountContext } from '../context/TestContext';

export default function TestComponent() {
    const { state, dispatch } = useCountContext();
    return (
            <View>
                <Text>子コンポーネントのここに表示→{state.count}</Text>
                <TouchableOpacity onPress={() => dispatch({ type: "decrement", count: state.count})}>
                    -
                </TouchableOpacity>
                <TouchableOpacity onPress={() => dispatch({ type: "increment", count: state.count})}>
                    +
                </TouchableOpacity>
            </View>
    );
};

【Contextファイル】

TestContext.jsx
import React, { createContext, useReducer, useContext }  from 'react';

const CountContext = createContext();

export function useCountContext() {
  return useContext(CountContext);
}

export function CountProvider({ children }) {

  //========
  // 初期値設定
  //========
  const initialState = {
    count: 100,
  };
  
  const reducer = (state, action) => {
    //========
    // 値変更処理
    //========
    if (action.type == "increment") {
      return { count: state.count + 1 };
    } else if (action.type == "decrement") {
      return { count: state.count - 1 };
    }
  };

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

  return (
    <CountContext.Provider value={ [state, dispatch ] }>
      {children}
    </CountContext.Provider>
  );
  
}

よろしくお願いいたします。

0

1Answer

useCountContext() がどのような値を返すのかを console.log() などで確認すると良いと思います。

1Like

Comments

  1. @cp716716

    Questioner

    回答いただきありがとうございます。
    console.log()で確認したところ、
    TestContext.jsxのvalueに渡していたstate,とdispatchが[]で囲われており、
    配列として値を渡していたことが原因でした。

    <CountContext.Provider value={[state, dispatch]}>
    の上記を以下に修正し無事解決しました。
    <CountContext.Provider value={{state, dispatch}}>

    どうもありがとうございました。
    初歩的なことでしたが、かなりハマっていたのでとても助かりました。
    今後はconsole.log()で確認することを習慣づけていきたいと思います。
  2. React Nativeでの開発に詳しくないのでひとまず `console.log()` でと書きましたが、もしかしたらもっとスマートなやり方があるかもしれません。

Your answer might help someone💌