実現したいこと
画面状態の遷移をContext + useReducerで外部管理して、
複数のコンポーネントからモードとその更新用関数を参照すること
学習なので本番実装を想定して、React.FC<Props>などは使いたくない
発生している問題・分からないこと
Providerの子要素になっているReactコンポーネントの返り値をすべてReactElementやReactNodeに変えているのにも関わらず なぜかElement[]と判断され、props等が存在しないといわれ怒られている状態なのですが、なぜ、Elementと判断されているのでしょうか?
エラーメッセージ
error
1型 '{ children: Element[]; }' には 型 'ReactElement<any, string | JSXElementConstructor<any>>[]' からの次のプロパティがありません: length, pop, push, concat、29 など。ts(2740)
該当のソースコード
typescript
1export default function MainPage():ReactElement { 2 return ( 3 <DisplayModeProvider> 4 <Header/> 5 <Main/> 6 </DisplayModeProvider> 7 8 ) 9}
TypeScript
1export default function Header():ReactElement{ 2 return ( 3 <div> 4 <img src="/logo.svg" className={styles.logo}/> 5 <Navigation menu_strs = {[ 6 C_MODE_STR.MODE_MUSTLIST_STR, 7 C_MODE_STR.MODE_SETTING_STR, 8 C_MODE_STR.MODE_HOWTONOTICE_STR 9 ]} orders = {C_MENU_ORDERS} 10 ></Navigation> 11 <hr></hr> 12 </div> 13 ); 14}
TypeScript
1export default function Navigation({ 2 menu_strs, 3 orders, 4}:{menu_strs:T_C_MODE_STR[],orders:number[]}):ReactElement{ 5 const {mode,DispatchMode}= useContext(DisplayModeContext); 6 7 8 return ( 9 <div> 10 {/* メニュー一覧 */} 11 <div className={Navigationstyles.menubox}> 12 { 13 orders.map( 14 (order) => { 15 return( 16 <div 17 className={` 18 ${Navigationstyles.menu} 19 ${Navigationstyles.hover_color} 20 ${GetModeStrFromMode(mode) === menu_strs[order] ? 21 Navigationstyles.menu_selected : 22 ""} 23 24 `} 25 onClick={(e) => { 26 DispatchMode( 27 { 28 mode:menu_strs[order] 29 } 30 ) 31 32 } 33 } 34 > 35 <IconLib 36 type = {menu_strs[order]} 37 classname = {Navigationstyles.menu_icon} 38 /> 39 {menu_strs[order]} 40 </div> 41 ) 42 } 43 ) 44 } 45 </div> 46 </div> 47 ) 48}
TypeScript
1import { C_MODE_STR } from "@/resources/Constant"; 2import ListIcon from '@mui/icons-material/List'; 3import SettingsIcon from '@mui/icons-material/Settings'; 4import HelpCenterIcon from '@mui/icons-material/HelpCenter'; 5import { T_C_MODE_STR } from "@/types/types"; 6import { ReactElement } from "react"; 7 8/** 9 * @module IconLib 10 * @description typeに応じて、Iconを返す\ 11 * 新しいアイコンを使用する際はこのモジュールに追加し\ 12 * IconLib経由で使うこと 13 * @param {I_IconlibParam} param : {\ 14 * type : C_MODE_STR内のいずれか\ 15 * classname : 使用したいstylename 必須ではない\ 16 * } 17 */ 18export default function IconLib({type,classname}:{type:T_C_MODE_STR,classname:string}):ReactElement{ 19 // typeの取得 20 let work_classname = ""; 21 if(classname != undefined){ 22 work_classname = classname; 23 } 24 //typeに応じたアイコンの表示 25 switch(type){ 26 case C_MODE_STR.MODE_SETTING_STR: 27 return( 28 <ListIcon className={work_classname}/> 29 ); 30 case C_MODE_STR.MODE_MUSTLIST_STR: 31 return( 32 <SettingsIcon className={work_classname}/> 33 ); 34 case C_MODE_STR.MODE_HOWTONOTICE_STR: 35 return( 36 <HelpCenterIcon className={work_classname}/> 37 ); 38 default: 39 return(<HelpCenterIcon className={work_classname}/>); 40 } 41 42}
TypeScript
1import { useReducer,ReactElement } from "react"; 2import { 3 C_MODE, 4 C_MODE_STR 5} from "../../resources/Constant"; 6import { C_MSG_WARN_TRANSIT 7 } from "@/resources/ErrorWarnString"; 8import { Dispatch,ReducerAction ,useRef} from "react"; 9import type { 10 T_TransitModeAction, 11 T_C_MODE 12} from "@/types/types"; 13import { createContext } from "react"; 14/** 15 * @method TransitModeState 16 * @description 画面状態遷移 17 * @param {T_C_MODE} state 18 * @param {T_TransitModeAction} action {mode: C_MODE_STRに定義されているいずれか} 19 * @returns {T_C_MODE} result_state 遷移判定後の画面状態 20 */ 21export function TransitModeState(state:T_C_MODE,action:T_TransitModeAction):T_C_MODE{ 22 let result_state:T_C_MODE = state; 23 switch(action.mode){ 24 case C_MODE_STR.MODE_MUSTLIST_STR: 25 result_state = C_MODE.MODE_MUSTLIST; 26 case C_MODE_STR.MODE_SETTING_STR: 27 result_state = C_MODE.MODE_SETTING; 28 case C_MODE_STR.MODE_HOWTONOTICE_STR: 29 result_state = C_MODE.MODE_HOWTONOTICE; 30 default: 31 console.warn(C_MSG_WARN_TRANSIT); 32 } 33 34 return result_state; 35} 36 37/** 38 * @method GetModeStrFromMode 39 * @description 現在のMODEをもとにMODE_STRを取得する 40 * @param {number} mode 41 * @return {string} MODE_STR 各モードに紐づけられた、文字列 42 */ 43export function GetModeStrFromMode(mode:number):string{ 44 switch(mode){ 45 case C_MODE.MODE_MUSTLIST: 46 return C_MODE_STR.MODE_MUSTLIST_STR; 47 case C_MODE.MODE_SETTING: 48 return C_MODE_STR.MODE_SETTING_STR; 49 case C_MODE.MODE_HOWTONOTICE: 50 return C_MODE_STR.MODE_HOWTONOTICE_STR; 51 default: 52 return ""; 53 } 54} 55 56 57 58export const DisplayModeContext = createContext( 59 {} as { 60 mode:T_C_MODE, 61 DispatchMode: Dispatch<T_TransitModeAction> 62 } 63); 64 65 66 67 68/** 69 * @module DisplayMode 70 * @method DisplayModeProvider 71 * @description 画面モード遷移用コンテキスト 72 * @param {ReactNode} children contextを使用する際のprovider 73 */ 74 export default function DisplayModeProvider(children:ReactElement[]):ReactElement{ 75 76 77 const [mode, DispatchMode] = useReducer( 78 TransitModeState, 79 C_MODE.MODE_INIT 80 ); 81 82 83 return( 84 <DisplayModeContext.Provider 85 value = { 86 { 87 mode, 88 DispatchMode 89 } 90 } 91 > 92 {children} 93 </DisplayModeContext.Provider> 94 95 ) 96} 97
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
エラー文やProvider 子要素 複数やReactコンポーネントデータ型などで検索
nextjs,react 公式ドキュメント typescriptのページを確認
Providerの子要素すべて(マテリアルUI以外)の戻り値をReactNode,ReactElementに変更
子要素が複数なのが問題なのかとProviderの引数のデータ型をReactNode | ReactNode[] のUnionにしたりReactElementとその配列のユニオンにしたり変更している
ただ、引数のデータ型をユニオンにしてもいかのエラーが出るだけで、進展なし
型 '{ children: Element[]; }' を型 'IntrinsicAttributes & (ReactElement<any, string | JSXElementConstructor<any>> | ReactElement<any, string | JSXElementConstructor<any>>[])' に割り当てることはできません。
補足
特になし
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。