React Router: переменная состояния, обновленная с помощью setState, не передается в Route правильно - PullRequest
0 голосов
/ 22 января 2019

Итак, у меня есть следующая проблема: Я хочу разрешить пользователям устанавливать язык моего портфолио. Для этого я предоставляю им две ссылки в исходном компоненте <Language />, которые устанавливают состояние <App />, а затем выводит пользователя на главный экран - <Home />. Проблема в том, что обновленный this.state.language не передается до <Home />; вместо этого передается начальное значение.

Мой код:

// <App /> component

class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            language: "none"
        }
    }

    changeLanguage = event => {
        event.preventDefault()
        this.setState({ language: event.target.id }, () => {
            window.location.href = "/home"
        })
    }

    render() {
        return (
            <BrowserRouter>
                <div id="app">
                    <Route
                        exact
                        path="/"
                        render={() => (
                            <Language changeLanguage={this.changeLanguage} />
                        )}
                    />
                    <Route
                        path="/home"
                        component={() => {
                            return <Home language={this.state.language} />
                        }}
                    />
                    <Route
                        path="/about"
                        render={() => {
                            return <About language={this.state.language} />
                        }}
                    />
                    <Route
                        path="/projects"
                        render={() => {
                            return <Projects language={this.state.language} />
                        }}
                    />
                    <Route
                        path="/contact"
                        render={() => {
                            return <Contact language={this.state.language} />
                        }}
                    />
                </div>
            </BrowserRouter>
        )
    }
}

// <Language /> component

const Language = props => {
    return (
        <div id="language">
            <h1>Choose your language.</h1>
            <div className="lang-options">
                <a
                    href="/home"
                    className="lang-link"
                    id="pt_BR"
                    onClick={props.changeLanguage}
                    title="Português Brasileiro"
                >
                    <img
                        src="https://s3-sa-east-1.amazonaws.com/myhostedfiles.raulf/Images/svg-icons/brazil-flag.svg"
                        alt="A bandeira brasileira. Clique para ter acesso ao site em português."
                    />
                </a>
                <a
                    href="/home"
                    className="lang-link"
                    id="en_US"
                    onClick={props.changeLanguage}
                    title="American English"
                >
                    <img
                        src="https://s3-sa-east-1.amazonaws.com/myhostedfiles.raulf/Images/svg-icons/usa-flag.svg"
                        alt="The american flag. Click to access the site in english."
                    />
                </a>
            </div>
            <h1>Escolha seu idioma.</h1>
        </div>
    )
}

// <Home /> component

const Home = (props) => {
    console.log(props.language)
    return (
        <div id="home">
            <div className="bg-filter" />
            <Navbar />
            <TypedIntro />
            <LinkBox />
        </div>
    )
}

Когда загружен компонент <Home />, console.log(props.language) регистрирует none на консоли, исходное значение которого this.state.language установлено на. Кто-нибудь может объяснить мне, почему он не будет обновляться, и как это исправить?

Ответы [ 4 ]

0 голосов
/ 22 января 2019

Вы должны использовать <Link to='/home'> вместо window.location.href = "/home".

Это перезагрузит страницу и перезагрузит компонент.Также отключает возможность реакции как SPA.

0 голосов
/ 22 января 2019

Настройка window.location.href будет обновлять страницу.Это потеряет все ваше состояние.Измените свои теги <a>, чтобы вместо них использовать тег реагирующего маршрутизатора <Link to="/home">.

Вот CodeSandbox, чтобы проиллюстрировать происходящее:

Edit yk1n96ynmz

0 голосов
/ 22 января 2019

У вас были проблемы, потому что вы использовали windows.location.href, это обновит приложение. И после этого вы получите новый экземпляр приложения, и вы потеряете состояние приложения. И это было причиной, по которой вы получали начальное состояние в консоли.

Измените windows.location.href на this.props.history.push(), но для этого вам нужно обернуть App компонент с withRouter HOC из'act-router-dom '. Я изменил ваш код в некоторых местах, проверьте это. И попробуйте использовать тег Link вместо тега a.

import { BrowserRouter , Route,  withRouter} from "react-router-dom";
.....

class App extends React.Component {
  constructor(props) {
      super(props)
      this.state = {
          language: "none"
      }
  }

  changeLanguage = event => {
      event.preventDefault()
      // react-router passes "history" as props
      this.setState({ language: event.target.id }, () => this.props.history.push('/home'))
  }

  render() {
      return (

          <div id="app">
            <Route
              exact
              path="/"
              render={() => (
                  <Language changeLanguage={this.changeLanguage} />
              )}
            />
            <Route
              path="/home"
              component={() => {
                  return <Home language={this.state.language} />
              }}
            />            
           </div>
      )
  }
}

// wrapping App component with "withRouter" HOC
const RouterApp = withRouter(App)

// <NewApp /> Component
// you need to do this because component wrapped inside
// "withRouter" HOC must be inside "Router" component
const NewApp = () => {
 return <BrowserRouter>
        <RouterApp />
  </BrowserRouter>
}

// <Language/> Component
const Language = props => {
  return (
      <div id="language">
          <h1>Choose your language.</h1>
          <div className="lang-options">
              <p
                  className="lang-link"
                  id="pt_BR"
                  onClick={props.changeLanguage}
                  title="Português Brasileiro"
              >
                  Português
              </p>
              <p
                  className="lang-link"
                  id="en_US"
                  onClick={props.changeLanguage}
                  title="American English"
              >
                  American
              </p>
          </div>
          <h1>Escolha seu idioma.</h1>
      </div>
  )
}   

// <Home Component/>
const Home = (props) => {
  console.log(props.language)
  return (
      <div id="home">
          Home Component
          <p>Language: {props.language}</p>
      </div>
  )
}

// render NewApp component
ReactDOM.render(<NewApp />, document.getElementById('root'));
0 голосов
/ 22 января 2019

Вы пытались исследовать это как решение?У вас будет файл, в котором вы определяете ключи для каждого языка и передаете объект i18n для доступа к каждому ключу.Это анти-шаблон, поскольку вы пытаетесь изменить состояние с помощью нескольких компонентов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...