Reactjs 在组件使用react/redux渲染之前从特定状态获取值?

Reactjs 在组件使用react/redux渲染之前从特定状态获取值?,reactjs,redux,react-redux,Reactjs,Redux,React Redux,我将react/redux与nodejs(express)/mongodb后端一起使用,以提供帮助 我希望在这里发生的是,如果一个用户试图去编辑一篇不属于他们的文章,我希望他们立即被重新路由,永远不会看到那个页面 比如说。用户“A”转到routelocalhost:8080/posts/post\u id/edit,但该帖子属于用户“B”。我希望用户A立即重新路由回该帖子或localhost:8080/posts/post\u id 在我的代码中,我可以通过一个名为getUser()的操作获取用

我将react/redux与nodejs(express)/mongodb后端一起使用,以提供帮助

我希望在这里发生的是,如果一个用户试图去编辑一篇不属于他们的文章,我希望他们立即被重新路由,永远不会看到那个页面

比如说。用户“A”转到route
localhost:8080/posts/post\u id/edit
,但该帖子属于用户“B”。我希望用户A立即重新路由回该帖子或
localhost:8080/posts/post\u 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));
import React,{Component}来自'React';
从“redux”导入{bindActionCreators};
从“../../actions/posts_actions”导入*作为操作;
从“../../actions/index”导入*作为actionsIndex;
从'redux form'导入{reduxForm,Field};
从'react redux'导入{connect};
从'react router dom'导入{Link};
类EditPost扩展组件{
组件willmount(){
if(this.props.auth){
console.log(this.props.auth);//->返回true
this.props.getUser();//->这会触发
}
}
componentDidMount(){
const{id}=this.props.match.params;
this.props.getOnePost(id);
if(this.props.auth){
if(this.props.user.\u id!==this.props.post.author.id){
this.props.history.push(`/posts/${id}`);
}
}
}
渲染场(场){
常量{meta:{toucted,error}}=field;
const className=`form group${moved&&error?'has danger':'}`;
返回(
{field.label}:
{触摸?错误:“”
)
}
onSubmit(值){
const{id}=this.props.match.params;
this.props.updatePost(值,id,()=>{
this.props.history.push(`/posts/${id}`);
});
}
render(){
const{handleSubmit}=this.props;
const{id}=this.props.match.params;
console.log(this.props.user);//->在三个空值之后显示用户
返回(
提交
取消
);
}
}
函数验证(值){
常量错误={};
如果(!values.title){
errors.title=“输入标题!”;
}
如果(!values.content){
errors.content=“请输入一些内容!”;
}
返回错误;
}
函数mapStateToProps({posts,auth,user},ownProps){
返回{
初始值:posts[ownProps.match.params.id],
post:posts[ownProps.match.params.id],
auth:auth.authenticated,
用户:用户
};
}
功能图DispatchToprops(调度){
返回bindActionCreators({…操作,…actionsIndex},分派);
}
导出默认连接(mapStateToProps、mapDispatchToProps)(reduxForm({
验证
表单:“编辑表单”
})(编辑);;
以下是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'));
“使用严格的”
从“React”导入React;
从“react dom”导入react dom;
从'react redux'导入{Provider};
从“react router dom”导入{BrowserRouter,Route,Switch};
从“redux”导入{applyMiddleware,createStore};
从“redux thunk”导入redux thunk;
从“./reducers/index”导入减缩器;
从“./components/App”导入应用程序;
导入“../style/style.css”;
从“./components/pages/Home”导入主页;
从“./components/Header”导入标题;
从“./components/Footer”导入页脚;
从“/components/auth/require_auth”导入RequireAuth;
从“/components/auth/require_unauth”导入RequireUnAuth;
从“./components/auth/Signin”导入登录;
从“/components/auth/Signup”导入注册;
从“/components/auth/Signout”导入签出;
从“./components/pages/Posts”导入帖子;
从“./actions/types”导入{AUTH_USER};
const createStoreWithMiddleware=applyMiddleware(reduxThunk)(createStore);
const store=createStoreWithMiddleware(reducers);
const token=localStorage.getItem('token');
如果(令牌){
dispatch({type:AUTH_USER});
}
常数路由=(
)
render(Routes、document.querySelector('.container');

如果
this.props.getUser()
是一个异步(thunk-ed)操作创建者,则不能保证在到达
组件安装时,该操作的结果可用

在尝试访问
componentDidMount
中的
this.props.user
字段之前,请在其中添加空检查

你能做的就是搬家

if(this.props.user._id !== this.props.post.author.id){
  this.props.history.push(`/posts/${id}`);
}
进入
组件将接收道具

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}`)
      }
    }
  }
组件上,将接收道具
-可能会清除一些问题

关于您的编辑,有几件事:

  • 如果您有许多依赖于
    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>
        )
      }
    } 
    
  • 就像我在评论中说的,缓存并从您的商店返回
    user
    。。。虽然看起来你已经在这么做了
  • 不要假设您始终可以访问
    用户
    ——请确保您正在对其进行空检查

  • 您在组件Willmount中使用的代码不属于此处

    this.props.getUser();
    
    您最好创建一个action creator,它处理promise+异步操作,然后通过状态/分派机制返回结果,以便稍后在componentDidMount生命周期钩子中使用

    Redux thunk示例调用API,请查看文档:


    this.props.getUser是一个action create,它使用axios向后端发送请求,获取用户,然后通过reducer将该用户状态设置为该用户
    this.props.getUser();
    
    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
      }
    }