reactjs - 如何在包装在 HOC 中的组件内使用 useContext() 挂钩?
问题描述
我有一个登录组件和一个应用程序组件。App 组件包含上下文 Provider 中的 Login 组件。Login 组件依次由 withFormik 高阶组件包装以进行表单验证。当我尝试在 Login 组件中使用 useContext() 挂钩时,它无法编译并出现以下错误:
./src/components/login/Login.jsx
第 12 行:在函数“login”中调用 React Hook “useContext”,该函数既不是 React 函数组件,也不是自定义 React Hook 函数 react-hooks/rules-of-hooks
也尝试过浏览 React 文档,但无法解决此问题。:(
登录.jsx:
import React, { useContext } from 'react';
import { withFormik, Form, Field } from 'formik';
import { RenderInput, RenderMobileNumberInput } from '../../utils/input.util';
import { isMobile, isPassword } from '../../utils/validation.util';
import AuthContext from '../../store/auth.store';
import '../../styles/login.scss';
const login = props => {
const authContext = useContext(AuthContext);
console.log('authContext', authContext);
return (
<div className="login-container">
<div className="login-content">
<h1 className="header">Agent Login</h1>
<div className="login-form">
<Form>
<div className="input-row">
<label htmlFor="mobile">Mobile Number</label>
<Field
component={RenderMobileNumberInput}
countrycode="+91"
name="mobile"
placeholder="Mobile Number"
validate={isMobile}
/>
</div>
<div className="input-row">
<label htmlFor="password">Password</label>
<Field
type="password"
component={RenderInput}
name="password"
placeholder="Enter Password"
validate={isPassword}
/>
</div>
<button className="btn btn-yellow" type="submit">
Login
</button>
</Form>
</div>
</div>
</div>
);
};
const FormikApp = withFormik({
mapPropsToValues(props) {
return {
mobile: props.mobile || '',
password: props.password || '',
};
},
handleSubmit(values) {
console.log(values);
},
})(login);
export default FormikApp;
应用程序.jsx:
// Importing required NPM modules
import React from 'react';
import { withRouter, Switch, Route } from 'react-router-dom';
// Importing local modules & components
import Login from './components/login/Login';
import AuthContext from './store/auth.store';
// Impoting stylesheets
import './App.scss';
function App() {
return (
<AuthContext.Provider value={{ isAuthenticated: false }}>
<div className="App">
<Switch>
<Route path="/" exact component={Login} />
</Switch>
</div>
</AuthContext.Provider>
);
}
export default withRouter(App);
auth.store.js:
import { createContext } from 'react';
const initialContext = {
user: null,
isAuthenticated: false,
};
const authContext = createContext({ ...initialContext });
export default authContext;
index.js:
/* eslint-disable react/jsx-filename-extension */
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.scss';
import App from './App';
import * as serviceWorker from './serviceWorker';
// Importing store contexts
import AuthContext from './store/auth.store';
ReactDOM.render(
<BrowserRouter>
<AuthContext.Provider value={{}}>
<App />
</AuthContext.Provider>
</BrowserRouter>,
document.getElementById('root')
);
serviceWorker.unregister();
解决方案
该错误准确地说明了它需要/想要说的内容。Hook 只能在 React 功能组件内部调用。https://reactjs.org/docs/hooks-rules.html
当您将login
组件编写为功能组件时,使用withForm
HOC 将其包装为类组件。您应该阅读withFormik
源代码以查看它:https ://github.com/jaredpalmer/formik/blob/next/src/withFormik.tsx 。
基本上,withFormik
HOC 所做的(以及许多其他 HOC 做同样的事情)是将您的组件包装在一个类组件中。这样做是为了让额外的道具(通常称为injected props
)可以传递给您的组件。
为了解决你的问题,你应该避免使用带有withFormik
HOC 的 react 钩子。您可以选择使用Formik
组件而不是withFormik
HOC。
推荐阅读
- python - 如何在 pyspark.bucketizer 中获取拆分值而不是存储桶索引
- terraform - terraform远程状态找不到属性
- typo3 - TYPO3 - tx_news:获取新闻模板之外当前可见新闻文章的详细视图数据
- c# - 在 JSON.Net 中反序列化期间使用类型解析属性名称
- vb.net - 增加标题栏文本限制
- html - 影响横幅 div 的多个 div
- r - 在事件之前和之后定义假人
- jquery - 为什么我的 ajax 函数不能用于无限滚动?
- matlab - 在 MATLAB 中设置多个复选框的值
- javascript - 使用 Electron 的 Web 视图中的缩放功能