AplexPlex
@AplexPlex

Почему React Router this.props.match.param не существует?

Не получается передать параметры в url при использовании react-router.
Github
<Switch>
      <Route exact path='/:id' component={ HocLoginComponet(LoginPage) } />
      <Route path='/student/test/:id' component={RouterComponentHOC(withAppLayout(<TesterForm />))}/>
      <Route path='/student' component={ RouterComponentHOC(withAppLayout(StudentForm)) }/>
      <Route path='/admin' component={ RouterComponentHOC(AdminPage)} />
      <Route path='/teacher' component={ RouterComponentHOC(TeacherPage)} />
      <Route path='*' component={NotFoundPage}/>
    </Switch>

Здесь указываю динамический путь к компоненту TesterForm при котором id передается в url и должен определятся как передаваемый параметр.
RouterComponentHOC
RouterComponentHOC
Это компонент для проверки авторизован пользователь или нет, и если нет отправляет на страницу авторизации.
Код RouterComponentHOC
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { asyncComponent } from 'react-async-component';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { AuthActions, IDispatchProps } from '../actions/authActions';
import { getRoleRequestFetch } from '../api/hocAuthApi';
import { IAppState } from '../types';
import { LoadingComponent } from './LoadingComponent';

const HocComponet = (Component: any) => {
  return asyncComponent({
    resolve: async () => {
      const data = await getRoleRequestFetch();
      interface IStateProps {
        authState: boolean;
        role_type: string;
      }

      type TProps = IDispatchProps & IStateProps;
      class RetComp extends React.Component<TProps> {
        public static contextTypes = {
          router: PropTypes.object,
        };
        constructor(props: any, context: any) {
          super(props, context);
        }
        public componentWillMount() {
          this.props.authActions.onUpdateAuth(data.auth, data.role_type);
        }
        public onRedirect = (url: string) => {
          return document.location.replace(url);
        }
        public onRoute = () => {
          if (data.role_type === `/${document.location.pathname.split('/')[1]}`) {
            return <Component/>;
          }
          return this.context.router.history.push('/404');
        }
        public render() {
          return <div> {
            !data.auth ? this.onRedirect('/') : this.onRoute()
          } </div>;
        }
      }
      function mapStateToProps(state: IAppState): IStateProps {
        return {
          authState: state.commonReducer.authState,
          role_type: state.commonReducer.role_type,
        };
      }

      function mapDispatchToProps(dispatch: Dispatch<IDispatchProps>): IDispatchProps {
        return {
          authActions: new AuthActions(dispatch),
        };
      }
      return connect(mapStateToProps, mapDispatchToProps)(RetComp);
    },
    LoadingComponent: () => <LoadingComponent/>,
  });
};
export default HocComponet;

withAppLayout
router.tsx
const withAppLayout = (Component: any) => (props: any) => <StudentPage><Component {...props} /></StudentPage>;

StudentPage.tsx
import * as React from 'react';

export class StudentPage extends React.Component {
  public render() {
    return <div className='container'>
      {this.props.children}
    </div>;
  }
}


Но не понимаю как получить данные параметры т.к. в компоненте расположенному по данному urlвыдает ошибку что this.props.match не существует.
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { IDispatchProps, StudentActions } from '../../actions/studentActions';
import { IAppState } from '../../types';
import { AnswerForm } from './AnswerForm';

interface IStateProps {
  serverConnectError: boolean;
  serverDataError: boolean;
  authState: boolean;
  activeTest: number;
  testIssuesList: [object];
  testState: [object];
}

type TProps = IDispatchProps & IStateProps;

class TesterForm extends React.Component<TProps> {
  public static contextTypes = {
    router: PropTypes.object,
  };
  constructor(props: any, context: any) {
    super(props, context);
  }
  public componentWillMount() {

    this.props.studentActions.getTestIssues(this.props.activeTest);
  }

  public render() {
    return(
      <div className='row'>
        <AnswerForm />
      </div>
    );
  }
}

function mapStateToProps(state: IAppState): IStateProps {
  return {
    serverConnectError: state.commonReducer.serverConnectError,
    serverDataError: state.commonReducer.serverDataError,
    authState: state.commonReducer.authState,
    activeTest: state.studentReducer.activeTest,
    testIssuesList: state.studentReducer.testIssuesList,
    testState: state.studentReducer.testState,
  };
}

function mapDispatchToProps(dispatch: Dispatch<IDispatchProps>): IDispatchProps {
  return {
    studentActions: new StudentActions(dispatch),
  };
}

const connectApp = connect(mapStateToProps, mapDispatchToProps)(TesterForm);

export {connectApp as TesterForm};
  • Вопрос задан
  • 6321 просмотр
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Вы не передаете в компонент props.
public onRoute = () => {
  if (data.role_type === `/${document.location.pathname.split('/')[1]}`) {
    return <Component/>;  // тут ничего не передается
  }
  return this.context.router.history.push('/404');
}

так должно работать:
public onRoute = () => {
  if (data.role_type === `/${document.location.pathname.split('/')[1]}`) {
    return <Component {...this.props} />;
  }
  return this.context.router.history.push('/404');
}

Как альтернативу HOC можно сделать обертку над Routе, применив композицию.
<AuthRoute path='/some_path' component={SomeComponent} />


Зачем вы используете context в компоненте дочернем router остается загадкой.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
AplexPlex
@AplexPlex Автор вопроса
Помимо этого я неправильно пытался получить данные.
Я пытался получить данные через.
this.props.match.param
Но match не существовало. Не знаю почему но при использовании connect Redux параметры передаются через него.
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { connect } from 'react-redux';
import { RouteComponentProps } from 'react-router-dom';
import { Dispatch } from 'redux';
import { IDispatchProps, StudentActions } from '../../actions/studentActions';
import { IAppState } from '../../types';
import { AnswerForm } from './AnswerForm';

interface IStateProps {
  serverConnectError: boolean;
  serverDataError: boolean;
  authState: boolean;
  activeTest: number;
  testIssuesList: [object];
  testState: [object];
  id: number;
}

interface IRouterProps {
  id: number;
}

type IProps = IStateProps & IRouterProps;

type TProps = IDispatchProps & IStateProps;

class TesterForm extends React.Component<TProps> {
  public static contextTypes = {
    router: PropTypes.object,
  };
  constructor(props: any, context: any) {
    super(props, context);
  }
  public componentWillMount() {
    alert(this.props.id);
    this.props.studentActions.getTestIssues(this.props.activeTest);
  }

  public render() {
    return(
      <div className='row'>
        <AnswerForm/>
      </div>
    );
  }
}

function mapStateToProps(state: IAppState, ownProps: RouteComponentProps<IRouterProps>): IProps {
  return {
    serverConnectError: state.commonReducer.serverConnectError,
    serverDataError: state.commonReducer.serverDataError,
    authState: state.commonReducer.authState,
    activeTest: state.studentReducer.activeTest,
    testIssuesList: state.studentReducer.testIssuesList,
    testState: state.studentReducer.testState,
    id: ownProps.match.params.id, // Здесь передаются параметрвы
  };
}

function mapDispatchToProps(dispatch: Dispatch<IDispatchProps>): IDispatchProps {
  return {
    studentActions: new StudentActions(dispatch),
  };
}

const connectApp = connect(mapStateToProps, mapDispatchToProps)(TesterForm);

export {connectApp as TesterForm};
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы