Can't make Context API work on React application, Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
Can't make Context API work on React application, Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
我正在尝试让 ContextAPI 在我的应用程序上运行,webpack 编译一切,但在浏览器上我得到
Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...)
is not iterable
这是我第一次尝试在项目中使用 ContextAPI。
在 index.js
ReactDOM.render(
<React.StrictMode>
<Router>
<RoutesTree />
</Router>
</React.StrictMode>,
document.getElementById('app')
);
在 RoutesTree.js
const DEFAULT_STATE = {
state: {
users: [],
teams: []
},
setState: () => {}
};
export const AppContext = createContext(DEFAULT_STATE);
const RoutesTree = () => {
const [state, setState] = useState(DEFAULT_STATE.state);
const value = useMemo(
() => ((state, setState)),
[state]
);
console.log('state', state);
return (
<AppContext.Provider value={value}>
<Routes>
<Route path='/' element={<App />} />
<Route path='/teams/:id' element={<Team />} />
</Routes>
</AppContext.Provider>
)
}
export default RoutesTree;
于 App.js(进行中)
const App = () => {
return (
<>
<Home />
</>
);
}
在 Home.js
const Home = () => {
const [state, setState] = useContext(AppContext);
useEffect(() => {
const getTeams = async () => {
const response = await axios.get(teamsApiUrl);
setState((prevState) => ({
teams: response.data,
users: prevState.users
}));
}
getTeams();
}, [])
完全错误:
Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
Home webpack://ecore-project/./src/components/Home/Home.js?:32
React 16
<anonymous> webpack://ecore-project/./src/index.js?:15
js http://localhost:8080/main.js:500
__webpack_require__ http://localhost:8080/main.js:1313
<anonymous> http://localhost:8080/main.js:2403
<anonymous> http://localhost:8080/main.js:2405 main.js line 434 > eval:32:78 The above error occurred in the <Home> component:
Home@webpack://ecore-project/./src/components/Home/Home.js?:32:78 App Routes@webpack://ecore-project/./node_modules/react-router/index.js?:922:7 RoutesTree@webpack://ecore-project/./src/components/RoutesTree/RoutesTree.js?:25:76 Router@webpack://ecore-project/./node_modules/react-router/index.js?:860:7 BrowserRouter@webpack://ecore-project/./node_modules/react-router-dom/index.js?:122:7
Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. react-dom.development.js:18572:15
React 16
<anonymous> webpack://ecore-project/./src/index.js?:15
js http://localhost:8080/main.js:500
__webpack_require__ http://localhost:8080/main.js:1313
<anonymous> http://localhost:8080/main.js:2403
<anonymous> http://localhost:8080/main.js:2405 Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
Home webpack://ecore-project/./src/components/Home/Home.js?:32
React 13
<anonymous> webpack://ecore-project/./src/index.js?:15
js http://localhost:8080/main.js:500
__webpack_require__ http://localhost:8080/main.js:1313
<anonymous> http://localhost:8080/main.js:2403
<anonymous> http://localhost:8080/main.js:2405
webpack 编译器:
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.0.100:8080/
<i> [webpack-dev-server] Content not from webpack is served from 'C:\Users\Alvaro\git\ecore-project\public' directory
asset main.js 1.84 MiB [emitted] (name: main)
asset ./index.html 230 bytes [emitted]
runtime modules 27.5 KiB 14 modules
modules by path ./node_modules/ 1.61 MiB 90 modules
asset modules 4.4 KiB
data:image/svg+xml,%3csvg xmlns=%27.. 281 bytes [built] [code generated]
data:image/svg+xml,%3csvg xmlns=%27.. 279 bytes [built] [code generated]
data:image/svg+xml,%3csvg xmlns=%27.. 161 bytes [built] [code generated]
data:image/svg+xml,%3csvg xmlns=%27.. 271 bytes [built] [code generated]
+ 12 modules
modules by path ./src/ 12.8 KiB
modules by path ./src/components/ 7.9 KiB 6 modules
modules by path ./src/*.js 683 bytes 2 modules
modules by path ./src/*.css 2.66 KiB 2 modules
./src/utils/usePagination.js 1.59 KiB [built] [code generated]
webpack 5.72.1 compiled successfully in 1741 ms
问题
问题在于您尝试计算记忆上下文值的方式。
const value = useMemo(
() => ((state, setState)), // <-- not an iterable value!
[state]
);
这并不完全是你想的那样,当 Home
组件尝试使用数组解构赋值访问状态和状态更新函数时,代码会崩溃。
const [state, setState] = useContext(AppContext); // <-- tries to access array
() => ((state, setState))
实际上是返回 Comma Operator 表达式的结果。 setState
函数是作为记忆值返回的。
使这个问题更加复杂的是上下文值被声明为对象而不是数组。
const DEFAULT_STATE = {
state: {
users: [],
teams: []
},
setState: () => {}
};
export const AppContext = createContext(DEFAULT_STATE);
解决方案
我确定您是想记忆一个对象。
const value = useMemo(
() => ({ state, setState }),
[state]
);
现在消费者需要正确解构对象。它是一个对象,而不是数组。
const { state, setState } = useContext(AppContext);
我正在尝试让 ContextAPI 在我的应用程序上运行,webpack 编译一切,但在浏览器上我得到
Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
这是我第一次尝试在项目中使用 ContextAPI。
在 index.js
ReactDOM.render(
<React.StrictMode>
<Router>
<RoutesTree />
</Router>
</React.StrictMode>,
document.getElementById('app')
);
在 RoutesTree.js
const DEFAULT_STATE = {
state: {
users: [],
teams: []
},
setState: () => {}
};
export const AppContext = createContext(DEFAULT_STATE);
const RoutesTree = () => {
const [state, setState] = useState(DEFAULT_STATE.state);
const value = useMemo(
() => ((state, setState)),
[state]
);
console.log('state', state);
return (
<AppContext.Provider value={value}>
<Routes>
<Route path='/' element={<App />} />
<Route path='/teams/:id' element={<Team />} />
</Routes>
</AppContext.Provider>
)
}
export default RoutesTree;
于 App.js(进行中)
const App = () => {
return (
<>
<Home />
</>
);
}
在 Home.js
const Home = () => {
const [state, setState] = useContext(AppContext);
useEffect(() => {
const getTeams = async () => {
const response = await axios.get(teamsApiUrl);
setState((prevState) => ({
teams: response.data,
users: prevState.users
}));
}
getTeams();
}, [])
完全错误:
Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
Home webpack://ecore-project/./src/components/Home/Home.js?:32
React 16
<anonymous> webpack://ecore-project/./src/index.js?:15
js http://localhost:8080/main.js:500
__webpack_require__ http://localhost:8080/main.js:1313
<anonymous> http://localhost:8080/main.js:2403
<anonymous> http://localhost:8080/main.js:2405 main.js line 434 > eval:32:78 The above error occurred in the <Home> component:
Home@webpack://ecore-project/./src/components/Home/Home.js?:32:78 App Routes@webpack://ecore-project/./node_modules/react-router/index.js?:922:7 RoutesTree@webpack://ecore-project/./src/components/RoutesTree/RoutesTree.js?:25:76 Router@webpack://ecore-project/./node_modules/react-router/index.js?:860:7 BrowserRouter@webpack://ecore-project/./node_modules/react-router-dom/index.js?:122:7
Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries. react-dom.development.js:18572:15
React 16
<anonymous> webpack://ecore-project/./src/index.js?:15
js http://localhost:8080/main.js:500
__webpack_require__ http://localhost:8080/main.js:1313
<anonymous> http://localhost:8080/main.js:2403
<anonymous> http://localhost:8080/main.js:2405 Uncaught TypeError: react__WEBPACK_IMPORTED_MODULE_0__.useContext(...) is not iterable
Home webpack://ecore-project/./src/components/Home/Home.js?:32
React 13
<anonymous> webpack://ecore-project/./src/index.js?:15
js http://localhost:8080/main.js:500
__webpack_require__ http://localhost:8080/main.js:1313
<anonymous> http://localhost:8080/main.js:2403
<anonymous> http://localhost:8080/main.js:2405
webpack 编译器:
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
<i> [webpack-dev-server] On Your Network (IPv4): http://192.168.0.100:8080/
<i> [webpack-dev-server] Content not from webpack is served from 'C:\Users\Alvaro\git\ecore-project\public' directory
asset main.js 1.84 MiB [emitted] (name: main)
asset ./index.html 230 bytes [emitted]
runtime modules 27.5 KiB 14 modules
modules by path ./node_modules/ 1.61 MiB 90 modules
asset modules 4.4 KiB
data:image/svg+xml,%3csvg xmlns=%27.. 281 bytes [built] [code generated]
data:image/svg+xml,%3csvg xmlns=%27.. 279 bytes [built] [code generated]
data:image/svg+xml,%3csvg xmlns=%27.. 161 bytes [built] [code generated]
data:image/svg+xml,%3csvg xmlns=%27.. 271 bytes [built] [code generated]
+ 12 modules
modules by path ./src/ 12.8 KiB
modules by path ./src/components/ 7.9 KiB 6 modules
modules by path ./src/*.js 683 bytes 2 modules
modules by path ./src/*.css 2.66 KiB 2 modules
./src/utils/usePagination.js 1.59 KiB [built] [code generated]
webpack 5.72.1 compiled successfully in 1741 ms
问题
问题在于您尝试计算记忆上下文值的方式。
const value = useMemo(
() => ((state, setState)), // <-- not an iterable value!
[state]
);
这并不完全是你想的那样,当 Home
组件尝试使用数组解构赋值访问状态和状态更新函数时,代码会崩溃。
const [state, setState] = useContext(AppContext); // <-- tries to access array
() => ((state, setState))
实际上是返回 Comma Operator 表达式的结果。 setState
函数是作为记忆值返回的。
使这个问题更加复杂的是上下文值被声明为对象而不是数组。
const DEFAULT_STATE = {
state: {
users: [],
teams: []
},
setState: () => {}
};
export const AppContext = createContext(DEFAULT_STATE);
解决方案
我确定您是想记忆一个对象。
const value = useMemo(
() => ({ state, setState }),
[state]
);
现在消费者需要正确解构对象。它是一个对象,而不是数组。
const { state, setState } = useContext(AppContext);