如果不在路线上(' /')在提交表单后转到该路线,请

时间:2017-03-30 00:42:56

标签: reactjs routes redux react-router react-boilerplate

我正在向api做出反应的搜索请求,它有效,我在所有路线上都有搜索栏渲染,所以当用户尝试使用搜索栏时,即使他不在主页中(' /&# 39;),它会将他重定向到该页面并呈现结果,当我尝试在其他路径中使用搜索栏时,请求被发送(主页状态更改,这是显示结果的路径)但是如果我尝试做browserHistory(' /')我收到错误,这样做的正确方法是什么

/*
 * searchBar
 *
 * This is the first thing users see of our App, at the '/' route
 */

import React from 'react';
import Helmet from 'react-helmet';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { browserHistory } from 'react-router';

import { makeSelectRepos, makeSelectLoading, makeSelectError } from 'containers/App/selectors';
import H2 from 'components/H2';
import ReposList from 'components/ReposList';
import AtPrefix from './AtPrefix';
import CenteredSection from './CenteredSection';
import Form from './Form';
import Input from './Input';
import Section from './Section';
import messages from './messages';
import { loadRepos } from '../../containers/App/actions';
import { changeUsername } from './actions';
import { makeSelectUsername } from './selectors';

import ActionBar from 'components/MainActionContainer/homepage';



import styled from 'styled-components';

const SearchWrapper = styled.div`
  position: absolute;
  top: 0px;
  right: 0px;
  padding-left: 4%;
  padding-right: 4%;
  padding-top: 30px;
  padding-bottom: 60px;
  height: 200px;
  display: flex;
  @media screen and (max-width: 360px) {
    width: 82%;
    position: absolute;
    top: -21px;
    right: 0px;
    height: 200px;
    padding-left: 4%;
    padding-right: 4%;
    padding-bottom: 60px;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
  }
`;

const InputSearch = styled.input`
  width: 90%;
  height: 100%;
  text-align: end;
  color: gray;
  padding-top: 45px;
  font-size: 2.8em;
  outline: 0;
  border-width: 0 0 2px 0;
  border-color: red;
  border-bottom: 2px solid red;
  font-family: district-pro, sans-serif;
  font-style: normal;
  font-weight: 100;
  margin-left: 10%;

  &:hover {
     background-color: #fff; 
  }

`;

const InputIcon = styled.div`
  float: right;
  height: 100%;
  margin-left: 5%;
  width: 11%;
  border-bottom: 2px solid red;
  padding-top: 40px;

  @media screen and (max-width: 360px) {
     padding-top: 60px;
  } 
`;

const Icon_eyeglass = styled.a`
  font-size: 3.5em;

  @media screen and (max-width: 360px) {
     font-size: 2.2em;
  }
`;




export class SearchBar extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
  /**
   * when initial state artist is not null, submit the form to load repos
   * 
   */
  componentDidMount() {
    if (this.props.username && this.props.username.trim().length > 0) {
      this.props.onSubmitForm();
    }
  }

  render() {
    const { loading, error, repos } = this.props;
    const reposListProps = {
      loading,
      error,
      repos,
    };

    return (
      <div>
        <Helmet
          title="Home Page"
          meta={[
            { name: 'description', content: 'Search upcoming concerts by your favorite Artist' },
          ]}
        />

        <SearchWrapper>
            <form onSubmit={this.props.onSubmitForm} autoComplete="off">
              <label htmlFor="username">
                <InputSearch
                  id="username"
                  type="text"
                  placeholder="Search"
                  value={this.props.username} 
                  onChange={this.props.onChangeUsername} 
                  autoComplete="off"
                />
              </label>
            </form>
             <InputIcon>
                  <Icon_eyeglass className="material-icons">search</Icon_eyeglass>
             </InputIcon>
        </SearchWrapper>
      </div>
    );
  }
}

SearchBar.propTypes = {
  loading: React.PropTypes.bool,
  error: React.PropTypes.oneOfType([
    React.PropTypes.object,
    React.PropTypes.bool,
  ]),
  repos: React.PropTypes.oneOfType([
    React.PropTypes.array,
    React.PropTypes.bool,
  ]),
  onSubmitForm: React.PropTypes.func,
  username: React.PropTypes.string,
  onChangeUsername: React.PropTypes.func,
};

export function mapDispatchToProps(dispatch) {
  return {
    onChangeUsername: (evt) => dispatch(changeUsername(evt.target.value)),
    onSubmitForm: (evt) => {
      if (evt !== undefined && evt.preventDefault) evt.preventDefault();
      dispatch(loadRepos());
    },
  };
}

const mapStateToProps = createStructuredSelector({
  repos: makeSelectRepos(),
  username: makeSelectUsername(),
  loading: makeSelectLoading(),
  error: makeSelectError(),
});

// Wrap the component to inject dispatch and state into it
export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);

我试过了:

export function mapDispatchToProps(dispatch) {
  return {
    onChangeUsername: (evt) => dispatch(changeUsername(evt.target.value)),
    onSubmitForm: (evt) => {
      if (evt !== undefined && evt.preventDefault) evt.preventDefault();
      dispatch(loadRepos())
      .then(
          () => {
              browserHistory.push('/');
          }
      )}
  };
}

但是去了错误

未捕获的TypeError:无法读取属性&#39; push&#39;未定义的

2 个答案:

答案 0 :(得分:0)

如果您使用的是react-router v4,则可以通过以下方式关联路线:

<Route path='/*' render={() => (this.state.repos ? ( <Redirect to='/' /> ) : ( <DefaultComponent /> ))} />

因此,如果有人抓取repos,他将被重定向到主页面,但是你必须在卸载组件之前清除状态以处理repos的下一次更新。

答案 1 :(得分:0)

您可以在主父<BrowserHistory>中使用<App>并在您的组件中使用this.props.history.push('/');