我正在使用react / redux和nodejs(express)/ mongodb后端的帮助。
我想在这里发生的是,如果用户试图编辑不属于他们的帖子,我希望他们立即重新路由并且永远不会看到该页面。
例如。用户" A"转到路由localhost:8080/posts/post_id/edit
,但该帖子属于用户" B"。我希望用户A立即重新路由回该帖子或localhost:8080/posts/post_id
。
在我的代码中,我可以让用户通过一个名为getUser()的操作,该操作向后端发送axios.get请求以获取当前登录的用户。我正在使用JWT令牌。不确定这是否是需要的信息。
这是代码,向您展示我想要做的事情。
import React , { Component } from 'react';
import { bindActionCreators } from 'redux';
import * as actions from '../../actions/posts_actions';
import * as actionsIndex from '../../actions/index';
import { reduxForm, Field } from 'redux-form';
import {connect} from 'react-redux';
import {Link} from 'react-router-dom';
class EditPost extends Component {
componentWillMount() {
if(this.props.auth) {
console.log(this.props.auth); // -> returns true
this.props.getUser(); // -> this fires off
}
}
componentDidMount() {
const {id} = this.props.match.params;
this.props.getOnePost(id);
if(this.props.auth){
if(this.props.user._id !== this.props.post.author.id){
this.props.history.push(`/posts/${id}`);
}
}
}
renderField(field) {
const { meta: {touched, error} } = field;
const className = `form-group ${touched && error ? 'has-danger' : ''}`;
return (
<div className={className}>
<label><strong>{field.label}:</strong></label>
<input
className="form-control"
type={field.type}
{...field.input}
/>
<div className="text-help">
{ touched ? error : ''}
</div>
</div>
)
}
onSubmit(values) {
const {id} = this.props.match.params;
this.props.updatePost(values, id, () => {
this.props.history.push(`/posts/${id}`);
});
}
render() {
const {handleSubmit} = this.props;
const {id} = this.props.match.params;
console.log(this.props.user); // -> shows me the user after three nulls
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field
label="Title"
name="title"
type="text"
component={this.renderField}
/>
<Field
label="Content"
name="content"
type="text"
component={this.renderField}
/>
<button type="submit" className="btn btn-success">Submit</button>
<Link to={`/posts/${id}`} className="btn btn-danger">Cancel</Link>
</form>
);
}
}
function validate(values) {
const errors = {};
if(!values.title) {
errors.title = "Enter a title!";
}
if(!values.content) {
errors.content = "Enter some content please!";
}
return errors;
}
function mapStateToProps({ posts, auth, user }, ownProps) {
return {
initialValues: posts[ownProps.match.params.id],
post: posts[ownProps.match.params.id],
auth: auth.authenticated,
user: user
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({...actions, ...actionsIndex}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(reduxForm({
validate,
form: 'editform'
})(EditPost));
以下是console.log语句:
这是index.js页面的编辑,有什么办法可以在这里更新用户状态吗?:
"use strict"
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import { applyMiddleware, createStore } from 'redux';
import reduxThunk from 'redux-thunk';
import reducers from './reducers/index';
import App from './components/app';
import '../style/style.css';
import Home from './components/pages/home';
import Header from './components/header';
import Footer from './components/footer';
import RequireAuth from './components/auth/require_auth';
import RequireUnAuth from './components/auth/require_unauth';
import Signin from './components/auth/signin';
import Signup from './components/auth/signup';
import Signout from './components/auth/signout';
import Posts from './components/pages/posts';
import {AUTH_USER} from './actions/types';
const createStoreWithMiddleware = applyMiddleware(reduxThunk)(createStore);
const store = createStoreWithMiddleware(reducers);
const token = localStorage.getItem('token');
if(token) {
store.dispatch({ type: AUTH_USER });
}
const Routes = (
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
)
ReactDOM.render(Routes, document.querySelector('.container'));
答案 0 :(得分:0)
如果this.props.getUser()
是异步(thunk-ed)动作创建者,则当您到达componentDidMount
在尝试访问其中的字段之前,在this.props.user
中为componentDidMount
添加空检查。
你能做的就是搬家
if(this.props.user._id !== this.props.post.author.id){
this.props.history.push(`/posts/${id}`);
}
进入componentWillReceiveProps
componentWillReceiveProps ({ user: nextUser }) {
const { history, match, user: currentUser, post } = this.props
const { id } = match.params
/* if you didn't previously have currentUser (i.e. after first load) - !currentUser
* or the user has changed - nextUser !== currentUser*/
if (!currentUser || nextUser !== currentUser) { // probably shouldn't use === here
/* the component might update before `this.props.getUser()` "returns", so make sure this is the
* update we are looking for by ensuring that we have nextUser - nextUser &&
* then get the id (nextUser._id), and run the check (!== post.author.id)*/
if (nextUser && (nextUser._id !== post.author.id)) {
history.push(`/posts/${id}`)
}
}
}
componentWillReceiveProps
上的{p> Here's a little light Friday reading - 可能会清除一些内容。
有关编辑的一些事项:
user
AuthComponent
HoC概念
class AuthComponent extends React.Component {
componentDidMount() {
if (!this.props.user) {
this.props.getUser()
}
}
render() {
// you could inject `user` into children here, but I would suggest that you
// instead store the result of `getUser` into a store like `redux` or `flux` and fetch from that in child components
return this.props.children
}
}
显然,你需要使用connect
并从状态中抓取user
来获取此组件。你会像
class SomeComponent extends React.Component {
render () {
return (
<AuthComponent>
<WrappedComponent/> // <- this is what's rendered
</AuthComponent>
)
}
}
您正在使用react-router
,因此更好的解决方案是将其纳入您的路由
<Route path="" component={AuthComponent}>
<Route path="some-path" component={WrappedComponent}/>
</Route>
user
...虽然看起来您已经这样做了user
- 请确保您无效检查答案 1 :(得分:0)
您在componentWillMount中使用的代码不属于此处。
this.props.getUser();
您最好创建一个动作redux-thunk创建者,它处理promise +异步操作,然后通过状态/调度机制返回结果,以便稍后在componentDidMount生命周期钩子中使用。
要调用API的Redux thunk示例,请查看redux-thunk docs:
const store = createStore(
reducer,
applyMiddleware(thunk.withExtraArgument(api))
)
// later
function fetchUser(id) {
return (dispatch, getState, api) => {
// you can use api here
}
}
To pass multiple things, just wrap them in a single object and use destructuring:
const store = createStore(
reducer,
applyMiddleware(thunk.withExtraArgument({ api, whatever }))
)
// later
function fetchUser(id) {
return (dispatch, getState, { api, whatever }) => {
// you can use api and something else here here
}
}