将基于Reaction路由器v4类的代码重写为基于v6功能的代码
我正在尝试使用Reaction和Spring Boot实现Oauh登录,我找到了一个可以遵循的教程。
我遇到的问题是它使用的是Reaction Router v4,我希望将其更新为使用Reaction Router v6并改用功能组件。
Login.js
import React, { Component } from 'react';
import './Login.css';
import { GOOGLE_AUTH_URL, FACEBOOK_AUTH_URL, GITHUB_AUTH_URL, ACCESS_TOKEN } from '../../constants';
import { login } from '../../util/APIUtils';
import { Link, Redirect } from 'react-router-dom'
import fbLogo from '../../img/fb-logo.png';
import googleLogo from '../../img/google-logo.png';
import githubLogo from '../../img/github-logo.png';
import Alert from 'react-s-alert';
class Login extends Component {
componentDidMount() {
// If the OAuth2 login encounters an error, the user is redirected to the /login page with an error.
// Here we display the error and then remove the error query parameter from the location.
if(this.props.location.state && this.props.location.state.error) {
setTimeout(() => {
Alert.error(this.props.location.state.error, {
timeout: 5000
});
this.props.history.replace({
pathname: this.props.location.pathname,
state: {}
});
}, 100);
}
}
render() {
if(this.props.authenticated) {
return <Redirect
to={{
pathname: "/",
state: { from: this.props.location }
}}/>;
}
return (
<div className="login-container">
<div className="login-content">
<h1 className="login-title">Login to SpringSocial</h1>
<SocialLogin />
<div className="or-separator">
<span className="or-text">OR</span>
</div>
<LoginForm {...this.props} />
<span className="signup-link">New user? <Link to="/signup">Sign up!</Link></span>
</div>
</div>
);
}
}
class SocialLogin extends Component {
render() {
return (
<div className="social-login">
<a className="btn btn-block social-btn google" href={GOOGLE_AUTH_URL}>
<img src={googleLogo} alt="Google" /> Log in with Google</a>
<a className="btn btn-block social-btn facebook" href={FACEBOOK_AUTH_URL}>
<img src={fbLogo} alt="Facebook" /> Log in with Facebook</a>
<a className="btn btn-block social-btn github" href={GITHUB_AUTH_URL}>
<img src={githubLogo} alt="Github" /> Log in with Github</a>
</div>
);
}
}
App.js
- 这是包含路由的App.js,我已将其更新为使用功能组件并响应路由器V6。
//imports left out
function App() {
const [globalUserState, setGlobalUserState] = useState({
authenticated: false,
currentUser: null,
loading: true
});
useEffect(() => {
loadCurrentlyLoggedInUser();
})
const loadCurrentlyLoggedInUser = () => {
getCurrentUser()
.then(res => {
setGlobalUserState({
currentUser: res,
authenticated: true,
loading: false
});
}).catch(err => {
setGlobalUserState({
loading: false
})
})
}
const handleLogout = () => {
localStorage.removeItem(ACCESS_TOKEN);
setGlobalUserState({
authenticated: false,
currentUser: null
});
Alert.success("You're safely logged out!");
}
return (
<Router>
<div className="app">
<div className="app-header">
<AppHeader />
</div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<SecuredRoute> <Profile /> </SecuredRoute>} />
<Route path="/login" element={(props) => <Login authenticated={globalUserState.authenticated} {...props} />} />
<Route path="/signup" element={(props) => <Signup authenticated={globalUserState.authenticated} {...props} />} />
<Route path="/oauth2/redirect" element={<OAuth2RedirectHandler />} />
<Route path="*" element={<Notfound />} />
</Routes>
<Alert stack={{limit: 3}}
timeout = {3000}
position='top-right' effect='slide' offset={65}
/>
</div>
</Router>
);
}
export default App;
我希望澄清什么
我很难理解V6(location.state.error、History y.place、location.pathname等)和功能组件(而不是基于类)的Reaction路由器功能的等价物。
另外,如果有人能解释一下这句话,请
<LoginForm {...this.props} />
解决方案
第一季度
我很难理解Reaction路由器的等价物 V6的功能(location.state.error,history.place, location.pathname等)和功能组件,而不是类 基于。
react-router-dom
V6中不再有路线道具,即没有history
、location
、match
。Route
组件也不再具有引用Reaction组件或返回JSX的函数的component
或render
道具,取而代之的是接受JSX文字的element
道具,即ReactElement。
如果我理解正确,您正在询问如何将RRDv6与类组件Login
和Signup
一起使用。
您有几个选项:
将
Login
和Signup
也转换为Reaction函数组件,并使用新的Reaction挂钩。我不介绍转换,但要使用的钩子是:
useNavigate
-history
对象已替换为navigate
函数。const navigate = useNavigate(); ... navigate("....", { state: {}, replace: true });
useLocation
const { pathname, state } = useLocation();
创建可使用挂钩并将其作为道具传递的自定义
withRouter
组件。const withRouter = WrappedComponent => props => { const navigate = useNavigate(); const location = useLocation(); // etc... other react-router-dom v6 hooks return ( <WrappedComponent {...props} navigate={navigate} location={location} // etc... /> ); };
修饰
Login
和Signup
导出:export default withRouter(Login);
从
this.props.history.push
切换到this.props.navigate
:componentDidMount() { // If the OAuth2 login encounters an error, the user is redirected to the /login page with an error. // Here we display the error and then remove the error query parameter from the location. if (this.props.location.state && this.props.location.state.error) { setTimeout(() => { const { pathname, state } = this.props.location; Alert.error(state.error, { timeout: 5000 }); this.props.navigate( pathname, { state: {}, replace: true } ); }, 100); } }
剩下的是修复App
中的路由,以便它们正确呈现JSX。
<Router>
<div className="app">
<div className="app-header">
<AppHeader />
</div>
<Routes>
<Route path="/" element={<Home />} />
<Route
path="/profile"
element={(
<SecuredRoute>
<Profile />
</SecuredRoute>
)}
/>
<Route
path="/login"
element={<Login authenticated={globalUserState.authenticated} />}
/>
<Route
path="/signup"
element={<Signup authenticated={globalUserState.authenticated} />}
/>
<Route path="/oauth2/redirect" element={<OAuth2RedirectHandler />} />
<Route path="*" element={<Notfound />} />
</Routes>
<Alert stack={{limit: 3}}
timeout = {3000}
position='top-right' effect='slide' offset={65}
/>
</div>
</Router>
第二季度
另外,如果有人能解释一下这行,请
<LoginForm {...this.props} />
这只是将传递给父组件的所有道具复制/传递到LoginForm
组件。
<LoginForm {...this.props} />
Login
传递一个authenticated
道具以及注入的任何新路线道具和您可能正在使用的任何其他HOC注入的任何其他道具,上述道具将一直传递给LoginForm
。
相关文章