Передача реквизитов компоненту из другого компонента, React Router v4

#javascript #reactjs #react-router #jsx

Вопрос:

Я пытаюсь передать реквизиты компоненту из другого компонента с помощью React Router v4, но не получаю желаемого результата.

Вот как я пытаюсь передать реквизит:

 render() {
    const { selectedLanguage, repos, error, dashboard } = this.state

    return (
      <React.Fragment>
        <LanguagesNav
          selected={selectedLanguage}
          onUpdateLanguage={this.updateLanguage}
        />

        {error amp;amp; <p>{error}</p>}

        {repos amp;amp; <LoginForm repos={repos} selected={selectedLanguage} dashboard={dashboard} onUpdateLogin={this.updateLogin} />}

        <Route
          path='/dashboard'
          render={(props) => (
            <Dashboard {...props}
              repos={repos}
              selected={selectedLanguage}
            />
          )}
        />
      </React.Fragment>
 

Весь компонент, из которого я хочу отправить реквизит:

Login.js

 import React from 'react'
import PropTypes from 'prop-types'
import languagesdata from '../languagesdata.json'
import { fetchLanguageRepos } from '../utils/api'
import Dashboard from './Dashboard'
import {BrowserRouter as Router, Route } from 'react-router-dom'
import { Link } from 'react-router-dom'

function LanguagesNav ({ selected, onUpdateLanguage}) {
  const languages = ['EU', 'ES', 'EN']

  return (
    <div >
      <h1 className='center-text header-lg'>
        GAUR 2.0
      </h1>
      <ul className='flex-center'>
        {languages.map((language) => (
          <li key={language}>
            <button
              className='btn-clear nav-link'
              style={language === selected ? { color: 'rgb(187, 46, 31)' } : null }
              onClick={() => onUpdateLanguage(language)}>
              {language}
            </button>
          </li>
        ))}
      </ul>
    </div>
  )
}

LanguagesNav.propTypes = {
  selected: PropTypes.string.isRequired,
  onUpdateLanguage: PropTypes.func.isRequired
}

function LoginForm ({ repos, selected, dashboard, onUpdateLogin }) {
  var language = {}
  switch (selected) {
    case "EU":
      selected = "EU";
      language  = repos[0].terms;
      break;
    case "ES":
      selected = "ES";
      language = repos[1].terms;
      break;
    case "EN":
      selected = "EN";
      language = repos[2].terms;
      break;
  }

  return (
    <form className='column player'>
      <div className='row player-inputs'>
        <input
          type='text'
          id='username'
          className='input-light'
          placeholder={language.username}
          autoComplete='off'
        />
      </div>
      <div className='row player-inputs'>
        <input
          type='password'
          id='password'
          className='input-light'
          placeholder={language.password}
          autoComplete='off'
        />
      </div>
      <div className='row player-inputs'>
        <Link
          className='btn dark-btn'
          to={{
            pathname: '/dashboard',
          }}
          >
            {language.login}
        </Link>
      </div>
    </form>
  )
}

LoginForm.propTypes = {
  repos: PropTypes.array.isRequired
}

export default class Login extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      selectedLanguage: 'EU',
      repos: null,
      error: null,
      dashboard: false
    }

    this.updateLanguage = this.updateLanguage.bind(this)

  }
  componentDidMount () {
    this.updateLanguage(this.state.selectedLanguage)
  }
  updateLanguage (selectedLanguage) {
    this.setState({
      selectedLanguage,
      error: null
    })

    fetchLanguageRepos(selectedLanguage)
      .then((repos) => this.setState({
          repos,
          error: null,
      }))
      .catch(() => {
        console.warn('Error fetching repos: ', error)

        this.setState({
          error: 'There was an error fetching the repositories.'
        })
      })
  }

  render() {
    const { selectedLanguage, repos, error, dashboard } = this.state

    return (
      <React.Fragment>
        <LanguagesNav
          selected={selectedLanguage}
          onUpdateLanguage={this.updateLanguage}
        />

        {error amp;amp; <p>{error}</p>}

        {repos amp;amp; <LoginForm repos={repos} selected={selectedLanguage} dashboard={dashboard} onUpdateLogin={this.updateLogin} />}

        <Route
          path='/dashboard'
          render={(props) => (
            <Dashboard {...props}
              repos={repos}
              selected={selectedLanguage}
            />
          )}
        />
      </React.Fragment>
    )
  }
}
 

И это тот компонент, на который я хочу отправить реквизит:

Dashboard.js

 import React from 'react'
import PropTypes from 'prop-types'
import Card from './Card'
import Loading from './Loading'
import { fetchLanguageRepos } from '../utils/api'
import Profile from './Profile'
import { Link } from 'react-router-dom'

function ReposGrid ({ repos, selected, profile, onUpdateProfile }) {
  var language = {}
  switch (selected) {
    case "EU":
      selected = "EU";
      language  = repos[0].terms;
      break;
    case "ES":
      selected = "ES";
      language = repos[1].terms;
      break;
    case "EN":
      selected = "EN";
      language = repos[2].terms;
      break;
  }

  return (
    <ul className='grid space-around'>
      <li key={language.studyplan}>
        <button
          onClick={() => {onUpdateProfile(`${profile}`)}}
        >
          <Card
            header={language.studyplan}
          >
          </Card>
        </button>
      </li>
      <li key={language.careers}>
        <Link to='/'>
          <Card
            header={language.careers}
          >
          </Card>
        </Link>
      </li>
      <li key={language.census}>
        <Card
          header={language.census}
        >
        </Card>
      </li>
      <li key={language.sms}>
        <Card
          header={language.sms}
        >
        </Card>
      </li>
      <li key={language.tuitions}>
        <Card
          header={language.tuitions}
        >
        </Card>
      </li>
      <li key={language.surveys}>
        <Card
          header={language.surveys}
        >
        </Card>
      </li>
      <li key={language.titles}>
        <Card
          header={language.titles}
        >
        </Card>
      </li>
      <li key={language.exams}>
        <Card
          header={language.exams}
        >
        </Card>
      </li>
      <li key={language.record}>
        <Card
          header={language.record}
        >
        </Card>
      </li>
    </ul>
  )
}

export default class Dashboard extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      selectedLanguage: 'EU',
      repos: null,
      error: null,
      loading: true,
      profile: false
    }

    this.updateProfile = this.updateProfile.bind(this)
  }

  componentDidMount () {
    var { repos, selectedLanguage } = this.props
    this.setState({
      selectedLanguage,
      repos,
      error: null,
      loading: false,
      profile: false
    })
  }

  updateProfile (profile) {
    this.setState({
      error: null,
      profile: true
    })
  }

  render() {
    const { selectedLanguage, repos, error } = this.props
    const { profile } = this.state

   if (profile === true) {
     return (
       <React.Fragment>
         {repos amp;amp; <Profile repos={repos} selectedLanguage={selectedLanguage} />}
       </React.Fragment>
     )
   }

    return (
      <React.Fragment>
        {repos amp;amp; <ReposGrid repos={repos} selected={selectedLanguage} profile={profile} onUpdateProfile={this.updateProfile} />}
      </React.Fragment>
    )
  }
}
 

I should be getting something like this:

expected dashboard

Instead, I’m getting this:

приборная панель, которую я получаю

Просто чтобы дать больше информации, это мое index.js где я наметил маршрут для Login.js:

index.js

 import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import Login from './components/Login'
import Dashboard from './components/Dashboard'
import Nav from './components/Nav'
import {BrowserRouter as Router, Route } from 'react-router-dom'

class App extends React.Component {
  render() {
    return (
      <Router>
        <div className='container'>
          <Nav />
          <Route exact path='/' component={Login} />
        </div>
      </Router>
    )
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
)
 

Я попытался проложить маршрут в index.js, но это тоже не сработало. Как правильно это сделать?

Комментарии:

1. Я полагаю, что наиболее подходящим решением для совместного использования состояния между несколькими разбросанными компонентами было бы Redux .

2. Почему вместо этого у вас есть dashboard маршрут внутри login app ? Лучше бы у вас были ваши реквизиты, которые нужно передать ребенку внутри App , а login не в том случае, если они не используются.

3. Как сказал @KavinduVIndika, странно, что у вас есть маршруты в разных компонентах… Перепишите свой код с помощью функциональных компонентов с нуля. Создайте все свои маршруты в App.js. Попробуйте передать реквизиты из дочернего компонента в другой через родительский компонент (App.js например) или с помощью Redux затем добавьте другие элементы…

4. Спасибо всем вам за ваши комментарии! Я понимаю, что неправильно разработал свой код, я собираюсь его переписать.