简体   繁体   English

当我尝试使用react-router-dom单击同一页面的同一链接时,最大更新深度超出了React

[英]Maximum update depth exceeded React when I try to click on the same link for the same page with react-router-dom

I have a header component like this : 我有这样的标题组件:

import React from "react"
import ProfilPicture from '../css/img/PROFILPICTURE.jpg';
import TravelmemoriesText from '../components/TravelmemoriesText/index';
import { Dropdown } from 'react-bootstrap'
import Searchbar from "./Searchbar";
import { Redirect } from 'react-router-dom'
import Config from '../Config'
import './styles.css'


class HomeHeader extends React.Component{
  constructor(props) {
    super()

    this.state = {
      fromChild: "",
      redirection: '',
      userName: '',
      userFirstName: ''
    }

    this.getDataFromSearchBar = this.getDataFromSearchBar.bind(this);
    this.goToFriends = this.getDataFromSearchBar.bind(this);
    this.goToProfile = this.goToProfile.bind(this);
    this.disconnect = this.disconnect.bind(this);
    this.goToHome = this.goToHome.bind(this);
  }

  goToProfile(){
    this.setState({
      redirection: <Redirect exact from="/" to={{
        pathname: '/profile',
        state: { thisUser: true }
    }} />
    })
  }

  goToFriends(){
    this.setState({
      redirection: <Redirect to='/friends' />
    })
  }

  goToHome(){
    this.setState({
      redirection: <Redirect to='/' />
    })
  }

  disconnect(){

    fetch('http://localhost:3001/disconnect', {
        method: 'POST',
        credentials: 'include',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': localStorage.getItem('xsrfToken')
        }
      })
      .then( () => {
        localStorage.removeItem('xsrfToken')
        this.setState({
          redirection: <Redirect to='/connexion' />
        })
      })  
  }

  getDataFromSearchBar(data, alpha3){
    this.props.openModal(data, alpha3)
  }

  componentDidMount(){
    fetch(Config.apiUrl + 'thisuser', {
      method: 'GET',
      credentials: 'include',
      headers: {
        "Authorization": localStorage.getItem("xsrfToken")
      }
    })
    .then(response => response.json())
    .then(body => {
      this.setState({
        userFirstName: body.firstName,
        userName: body.name
      })
    })
    .catch(err => {
      console.log("Erreur de chargement de l'API")
    })   
  }

  render(){
    return(
      <div className="navBar">
      {this.state.redirection}
      <div className="navHeader"
        onClick={this.goToHome}>
        <TravelmemoriesText />
      </div>
      <div className="navBody">
        <div className="searchPadding">
        <Searchbar openModal={this.getDataFromSearchBar} />
        </div>
      </div>
      <div className="navFooter">
        <Dropdown>
          <Dropdown.Toggle>
          <div className="profilName">
            {this.state.userFirstName} {this.state.userName}
          </div>
          <img src={ProfilPicture} className="profilPicture" />
          </Dropdown.Toggle>

          <Dropdown.Menu>
            <Dropdown.Header>
              <img src={ProfilPicture} className="dropdownPicture" />
              <div className="dropdownProfilName text-center">
              {this.state.userFirstName} {this.state.userName}
              </div>
              <div className="dropdownProfilStatus text-center">
                Globe Trotteur
              </div>
             </Dropdown.Header>
            <Dropdown.Item
              onClick={this.goToProfile}
            >Profil</Dropdown.Item>
            <Dropdown.Divider />
            <Dropdown.Item
              onClick={this.goToFriends}
            >Amis</Dropdown.Item>
            <Dropdown.Divider />
            <Dropdown.Item
              onClick={this.disconnect}
            >Se déconnecter</Dropdown.Item>
          </Dropdown.Menu>
        </Dropdown>
      </div>
      </div>             
    )
  }
}

export default HomeHeader;

Then I have a Profile component where goes the redirection when click on link "Profil" : 然后,我有一个Profile组件,当单击链接“ Profil”时该重定向到哪里:

import React, { Component } from "react"
import Header from '../Header'
import ModalCountry from '../ModalCountry'
import './styles.css'

class Profile extends Component {
    constructor(props){
        super(props)

        this._child = React.createRef();

        this.state = {
            modalTitle: '',
            alpha3: '',
            thisUser: this.props.location.state ? this.props.location.state.thisUser : ""
        }

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

    componentDidMount(){
        console.log(this.state.thisUser)
    }

    getDataFromSearchBar(data, alpha3){
        this.setState({
          modalTitle: data,
          alpha3: alpha3
        }, () => {
          this._child.current.open()
        })
    }

    render() {
        return (
            <div className="wrapperStyles">
                <Header openModal={this.getDataFromSearchBar} />
                <ModalCountry ref={this._child} modalTitle={this.state.modalTitle} alpha3={this.state.alpha3} />
            </div>
        )
    }
}

export default Profile

My routes are managed like this in index.js : 我的路线在index.js中这样管理:

import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.css';
import {
    BrowserRouter as Router,
    Route,
    Switch,
    withRouter
} from 'react-router-dom'
import App from './App';
import Connexion from './screens/Connexion/index.js';
import * as serviceWorker from './serviceWorker';
import Test from './Test';
import Profile from './screens/Profile/Profile.js';
import Security from './Security';

const Root = () => {
    return (
        <Router>
            <Switch>
                <Route exact path='/' component={Security(App)} />
                <Route exact path='/connexion' component={Connexion} />
                <Route exact path='/test' component={Test} />
                <Route exact path='/profile' component={Profile} />
            </Switch>
        </Router>
    )
}

ReactDOM.render(<Root />, document.getElementById('root'));

If I click many times on the link "Profil" in the header, when I am on the profile page, I got an error from react : 如果我多次单击标题中的链接“ Profil”,则在个人资料页面上时,我从react得到一个错误:

在此处输入图片说明

My functions are bind correctly, I also tried with {() => function()} to call my functions inside components. 我的函数正确绑定,我也尝试使用{{)=> function()}在组件内部调用我的函数。 Is it because of Redirect component from react-router-dom? 是因为从react-router-dom重定向组件?

Edit: Here is Searchbar component which was missing : 编辑:这是缺少的Searchbar组件:

import React from 'react';
import { components } from 'react-select';
import Select from 'react-select'
import Config from '../Config';
import './styles.css'

const { Option } = components;

const IconOption = (props) => 
  (
    <Option {... props}>
      <div>
        <img className="img-searchbox" src={props.data.alpha2 == "CS" ? process.env.PUBLIC_URL + "/img/flags_mini/" + props.data.alpha2 + ".png" : props.data.icon} />
        {props.data.label}
      </div>
    </Option>
  );

const customStyle = {      
  control: () => ({
    borderBottom: '1 !important',
    borderRight: '0 !important',
    borderLeft: '0 !important',
    borderTop: '0 !important',

    // This line disable the blue border
    boxShadow: '0 !important',
  }),

  menu: (provided) => ({
    ...provided,
    backgroundColor: "rgba(244, 241, 236, 0.5)"
  })
}

class Searchbar extends React.Component {
  constructor(props){
    super(props)

    this.state = {
      selectedOption: null,
      options: []
    }
  }

  handleChange = selectedOption => {
    if(selectedOption.type == "country"){
      this.props.openModal(selectedOption.label, selectedOption.alpha3)
    }
  };

  componentDidMount(){
    let arr = [];

    fetch(Config.apiUrl + 'country', {
      method: 'GET',
      credentials: 'include',
      headers: {
        "Authorization": localStorage.getItem("xsrfToken")
      }
    })
    .then(response => response.json())
    .then(body => {
        body.forEach(function(country){
          arr.push({ value: country.name_fr, label: country.name_fr, type: "country", alpha3: country.alpha3, alpha2: country.alpha2, icon: 'https://www.countryflags.io/' + country.alpha2.toLowerCase() + '/shiny/32.png'})
        })
    })
    .then(() => {
      fetch(Config.apiUrl + 'users_info', {
        method: 'GET',
        credentials: 'include',
        headers: {
          "Authorization": localStorage.getItem("xsrfToken")
        }
      })
      .then(response => response.json())
      .then(body => {
          body.forEach(function(user){
            arr.push({ value: user.firstName, label: user.firstName + ' ' + user.name, type: "user" })
          })
      })
      .then(() => {
        this.setState({
          options: arr
        })
      })
      .catch(err => {
        console.log("Erreur de chargement de l'API")
      })
    })
    .catch(err => {
      console.log("Erreur de chargement de l'API")
    })
  }

  render() {
    return (
      <Select
        classNamePrefix="react-select"
        placeholder={"Search..."}
        onChange={this.handleChange}
        components={{ DropdownIndicator: () => null, Option: IconOption }}
        options={this.state.options}
        openMenuOnClick={false}
        styles={customStyle}
        getOptionLabel={(option)=>option.label}
        getOptionValue={(option)=>option.value}
      />
    );
  }
}

export default Searchbar;

This error comes when we have set state under render function or if we use componentDidUpdate without if condition But in your case, 当我们在渲染功能下设置了状态,或者如果我们在没有if条件的情况下使用componentDidUpdate时,就会发生此错误。

<Header openModal={this.getDataFromSearchBar} />

You are passing openModal as props and using 您将openModal作为道具传递并使用

<Searchbar openModal={this.getDataFromSearchBar} />

So if you are passing open modal then instead of this.getDataFromSearchBar you have to use this.props.openModal 因此,如果要传递开放模式,则必须使用this.props.openModal而不是this.getDataFromSearchBar

Try it let see 试试看吧

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM