[英]Convert React Context API Class to function of Hook
如何更改此类基础 Context API 以到达 Hook,而无需更改已使用它的其他组件? 我是新来的反应和整夜,我被卡住了。
实际代码不止这些,但为了简单起见,我试图删除一些代码:
import React, { createContext, Component } from 'react'
const MainContext = createContext();
class MainContextProvider extends Component {
state = {
isLogin : false,
loginData : [],
spinner : false
}
handleUserLogin = (res) => {
this.setState({
...this.state,
isLogin : res.isLogin,
loginData : res.data
})
}
showSpinner = (status) => {
this.setState({
...this.state,
spinner : status
})
}
render() {
console.log(this.state)
return (
<MainContext.Provider value = {{
...this.state,
showSpinner : this.showSpinner,
handleUserLogin : this.handleUserLogin,
}}>
{this.props.children}
</MainContext.Provider>
);
}
}
const MainContextConsumer = MainContext.Consumer;
export {MainContextProvider, MainContextConsumer, MainContext};
我用这个 MainContextProvider 包装 index.js 以便所有组件都可以使用状态或使用方法。
以下是如何使用带有钩子的context
并保持与现有 API 相同的 API:
import React, { createContext, useContext, useState } from "react";
import "./style.css";
// Define your context, this is the same
const MainContext = createContext();
function Provider({ children }) {
// Define some state to hold the data
let [state, setState] = useState({
isLogin: false,
loginData: [],
spinner: false
});
// Define a few functions that change the state
let handleUserLogin = res => {
setState(s => ({
...s,
isLogin: res.isLogin,
loginData: res.data
}));
};
// Define a few functions that change the state
let showSpinner = status => {
setState(s => ({ ...s, spinner: status }));
};
// Pass the `state` and `functions` to the context value
return (
<MainContext.Provider
value={{ ...state, handleUserLogin, showSpinner }}
>
{children}
</MainContext.Provider>
);
}
function Stuff() {
// Inside your component use the context with `useContext` hook
let { showSpinner, handleUserLogin, ...state } = useContext(MainContext);
return (
<div>
<div>
<code>{JSON.stringify(state, null, 2)}</code>
</div>
<button onClick={() => showSpinner(Math.random())}>
Show Spinner
</button>
</div>
);
}
export default function App() {
return (
<Provider>
<Stuff />
</Provider>
);
}
作为 Sam R. 的建议,我几乎没有修改并按预期工作。 也许使用 Reducer 更好,但我不喜欢。 而且我认为 Context API 比 Redux 更简单。
主上下文.js :
import React, { createContext, useState } from 'react'
const MainContext = createContext();
const MainContextProvider = ({ children }) => {
// Define some state to hold the data
let [state, setState] = useState({
isLogin: false,
loginData: [],
spinner: false
});
// Define a few functions that change the state
let handleUserLogin = res => {
setState(s => ({
...s,
isLogin: res.isLogin,
loginData: res.data
}));
};
// Define a few functions that change the state
let showSpinner = status => {
setState(s => ({ ...s, spinner: status }));
};
// Pass the `state` and `functions` to the context value
return (
<MainContext.Provider
value={{ ...state, handleUserLogin, showSpinner }}
>
{children}
</MainContext.Provider>
);
}
const MainContextConsumer = MainContext.Consumer;
export {MainContextProvider, MainContextConsumer, MainContext};
登录.js:
import React, { useState, useContext } from "react";
import { Link } from "react-router-dom";
import { useHistory } from "react-router-dom";
import {MainContext} from "../contextApi/MainContext";
import { login } from "../api/Api_User";
const Login = () => {
const history = useHistory();
const { handleUserLogin, showSpinner } = useContext(MainContext);
const [user , setUser] = useState({ email : "", password : "" })
const [errors , setErrors] = useState({ emailErr : "", passErr : "" })
const handleChange = e => {
const {name , value} = e.target
setUser( prevState => ({ ...prevState,[name] : value }))
setErrors({ emailErr : "", passErr : "" });
}
const handleSubmit = (e) => {
// client side validation
if(!user.email) { setErrors({ emailErr : "Please enter email" }); return false; }
if(!user.password) { setErrors({ passErr : "Please enter password" }); return false; }
showSpinner(true)
const data = {
email: user.email,
password: user.password
}
// axios call
login(data).then(res => {
setTimeout(() => {
showSpinner(false)
if (res) {
if (res.status === true) {
localStorage.setItem("token", res.token); // jwt token from server
handleUserLogin(res) // store server respond to global states
return history.push('/dashboard')
}
// server side validation
if (res.status === false) {
res.path === 'email' && setErrors({ emailErr : res.message })
res.path === 'password' && setErrors({ passErr : res.message })
}
}
},100 )
});
}
return (
<div className="page">
<div className="page-content mt-5 mb-5">
<div className="content-sticky-footer">
<div className="container">
<div className="row">
<div className="col">
<div className="card mb-0">
<div className="card-header">
<h3 className="mx-auto mt-4">LOGIN MEMBER</h3>
</div>
<div className="card-body">
<div className="form-group">
<label>Email address *</label>
<input
type="email" className="form-control"
name="email"
value={user.email}
onChange={handleChange}
/>
<span className="text-danger label-sm ">
{errors.emailErr}
</span>
</div>
<div className="form-group">
<label>Password *</label>
<input
type="password" className="form-control"
name="password"
value={user.password}
onChange={handleChange}
/>
<span className="text-danger label-sm ">
{errors.passErr}
</span>
</div>
<div className="form-footer mt-2">
<button
type="button"
className="btn btn-primary btn-block btn-lg btn-submit"
onClick={handleSubmit}
>
Login
</button>
</div>
<div className="text-center mt-3 text-dark">
Do not have account?
<Link to="/register"> Register</Link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default Login
索引.js :
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './css/App.css';
import App from './App';
import { BrowserRouter} from "react-router-dom";
import {MainContextProvider} from './contextApi/MainContext';
import axios from "axios";
// express server with mongodb
axios.defaults.baseURL = "http://localhost:3001";
ReactDOM.render(
<MainContextProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</MainContextProvider>,
document.getElementById('root')
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.