与react-router-dom 4反应 - 无法读取属性' params'未定义的

时间:2018-04-19 16:23:22

标签: javascript reactjs react-router-v4

我一直在努力学习React以确定它是否适合我的组织需求,所以不用说我是新手。我有一个示例应用程序,我一直在努力查看它是如何工作的。我已经在这里找到了几个答案,并且没有找到解决我问题的答案。

  我遇到了问题,我得到了一个" Uncaught(承诺)TypeError:无法读取属性' params'未定义"在" componentDidMount()" at" const {match:{params}} = this.props;"下面组件中的方法。我有一个非常相似的组件,使用相同的方法从URL中获取id,并且它工作正常。我很困惑为什么一个人在工作而另一个人没有工作。我可能只是在某个地方犯了一个新手的错误(也许不止一个),任何提示/答案都会受到赞赏。

路由:

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <div>
          <Route path='/' component={BaseView} />
          <Route path='/test' component={NameForm} />
          <Route path='/home' component={Home} />
          <Route path='/quizzes' component={ViewQuizzes} />
          <Route path='/comment/:rank' component={GetCommentsId}  /*The one that works*//>
          <Route path='/comment/edit/:testid' component={GetCommentEdit} /*The one I'm having trouble with*//> 
          <Route path='/comments' component={GetCommentsAll} />
        </div>
      </BrowserRouter>
    );
  }
}

工作组件:

class GetCommentsId extends Component{

  constructor (props) {
    super(props)
    this.state = {
      Comments: [],
      output: "",
      wasClicked: false,
      currentComment: " ",
    }

    this.handleCommentChange = this.handleCommentChange.bind(this);
  }

  componentDidMount(){
    const { match: { params } } = this.props;
    const url = 'http://localhost:51295/api/Values/' + params.rank;

    axios.get(url).then(res => {
      const comments = res.data;
      this.setState({ comments });      
      this.output = (
        <div>
          <ul>
            { this.state.comments.map
            (
              comment => 
              (<Comment 
                QuizId = {comment.Rank} 
                FirstName = {comment.FirstName} 
                Comments = {comment.Comments}
                TestId = {comment.TestimonialId}
              />)
            )} 
          </ul>
        </div>
      );
      //console.log("From did mount: " + this.currentComment);
      this.forceUpdate();
    });
  }

  componentDidUpdate(){}

  handleCommentChange(event){
    //console.log("handle Comment Change activated");
  }

  handleClick(comment){
    this.wasClicked = true;
    this.currentComment = comment.Comments;
    console.log(comment.Comments);
    this.forceUpdate();
  }

  render () {
    if(this.output != null){
      if(!this.wasClicked){
        return (this.output);
      }
      else{
        console.log("this is the current comment: " + this.currentComment);
        return(
          <div>
            {this.output}
            <NameForm value={this.currentComment}/>
          </div>
        );
      }
    }
    return ("loading");
  }
}

那个没有工作的人:

class GetCommentEdit extends Component {
  constructor (props) {
    super(props)
    this.state = {
      Comments: [],
      output: "",
      match: props.match
    }
  }

  componentDidMount(){
    const { match: { params } } = this.props;
    const url = 'http://localhost:51295/api/Values/' + params.testid;

    axios.get(url).then(res => {
      const comments = res.data;
      this.setState({ comments });      
      this.output = (
        <div>
          <ul>
            { this.state.comments.map
            (comment => 
              (<EditComment 
                QuizId = {comment.Rank} 
                FirstName = {comment.FirstName} 
                Comments = {comment.Comments}
                TestId = {comment.TestimonialId}
              />)
            )} 
          </ul>
        </div>
      );
      //console.log("From did mount: " + this.currentComment);
      this.forceUpdate();
    });
  }

  render(){
    return(
      <div>
        {this.output}
      </div>
    );
  }
}

1 个答案:

答案 0 :(得分:2)

我已经为您创建了一个小应用,以演示如何实现工作react router v4

在每条路线上都有一堆道具,你可以看到那里的参数可以看到。

在您的代码中,我不明白为什么您没有使用Switch中的react-router v4,您的路线也没有exact旗帜/道具。这样,您就不会一个接一个地渲染组件视图。

指向沙箱的链接:https://codesandbox.io/s/5y9310y0zn

请注意,建议在App组件周围包裹withRouter,App组件不应包含<BrowserRouter>

查看代码

请注意,更新状态会触发组件的新渲染。

不要使用此处不需要的this.forceUpdate(),而是使用解析Promise / axios请求所获得的值来更新您的状态。

  // Bad implementation of componentDidMount
  // Just remove it
  this.output = (
    <div>
      <ul>
        {this.state.comments.map
          (
          comment =>
            (<Comment
              QuizId={comment.Rank}
              FirstName={comment.FirstName}
              Comments={comment.Comments}
              TestId={comment.TestimonialId}
            />)
          )}
      </ul>
    </div>
  );
  //console.log("From did mount: " + this.currentComment);
  this.forceUpdate();

在render方法或任何其他辅助方法中移动循环函数,这里是使用辅助方法的代码。

renderComments() {
  const { comments } = this.state;

  // Just check if we have any comments
  // Return message or just return null
  if (!comments.length) return <div>No comments</div>;

  // Move li inside loop
  return (
    <ul>
      {comments.map(comment => (
        <li key={comment.id}>
          <Comment yourProps={'yourProps'} />
        </li>
      ))}
    </ul>
  )
};

在初始状态中添加isLoading之类的内容。每次完成提取或开始提取时,都会切换为加载状态。

this.setState({ isLoading: true }); // or false

// Initial state or implement in constructor
state = { isLoading: true };

渲染方法将向我们显示每次加载内容时加载,renderComments()将返回我们的评论。我们得到干净可读的代码。

render() {
  if (isLoading) {
    return <div>Loading...</div>
  }

  return (
    <div>
      {this.renderComments()}
    </div>
  );
}