Как сохранить имя страницы и URL в React to Redux store при каждой загрузке - PullRequest
0 голосов
/ 05 апреля 2019

Ниже обновлений кода, pageName и pageURL в моем Redux Store для пользователя, и я получаю это обновление, когда пользователь просматривает приложение реагирования.

const { match } = this.props;
if(match.params.type) {
  this.props.pageURL(match.url);
  this.props.pageName((match.params.type).replace(/-/g, " "));
}

Если я помещаю этот код в метод render() {, все работает нормально, но я получаю следующее сообщение об ошибке:

Warning: Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.

Если я помещу его между определением класса и рендерингом

class Skeleton extends Component {  
  render () { 

Это не работает, имя страницы и URL в магазине остаются старыми, даже когда пользователь перемещается.

Ниже я покажу, как настроить Props, поэтому у меня есть App.js сэтот код:

<Provider store={store}>
    <BrowserRouter>
        <Fragment>
           <Route exact path="/" component={Skeleton} />  
           <Route path="/:type" component={Skeleton} />
      </Fragment>
    </BrowserRouter>
  </Provider>

Он направляет пользователя в Skeleton в любом случае, если реквизиты совпадают, поэтому я могу выяснить, находится ли пользователь на домашней странице / или какой-то другой, то есть /Daily, а затем на Skeleton Iзагружает части страницы, а также сохраняет, на какую страницу пользователь пытался перейти.Это имя страницы и URL-адрес сохранены в хранилище редуксов, чтобы все компоненты знали, какую страницу пользователь пытается посетить.

Полный код

// 
import React, { Component, Fragment } from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';

// Parts of the page
import Sidebar from './Skeleton/Sidebar';
import Content from './Skeleton/Content';
import TopBar from './Skeleton/TopBar';

// Redux
import { connect } from 'react-redux';
import { pageName, pageURL } from './../redux/actions';

class Skeleton extends Component {  
  render () { 
    const { match } = this.props;
    if(match.params.type) {
      this.props.pageURL(match.url);
      this.props.pageName((match.params.type).replace(/-/g, " "));
    }

    return (
      <Fragment>
        <CssBaseline />
        <TopBar />
        <Sidebar /> 
        <Content />
      </Fragment>
    )
  }
}

function mapStateToProps(state) {
  return {
    pageURL,
    pageName
  }
}

const mapDispatchToProps = dispatch => {
  return {
    pageName: Name => dispatch(pageName(Name)),
    pageURL: URL => dispatch(pageURL(URL)),
  }
}

export default connect(mapStateToProps, mapDispatchToProps) (Skeleton);

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

Так же, как и в сообщении об ошибке, вы не должны обновлять состояние во время рендеринга, способ добиться этого - проверить изменения вашего состояния / реквизита перед вызовом вашей функции, чтобы избежать бесконечного цикла рендеринга. Попробуйте это:

componentDidUpdate(prevProps) {
  const {
    match: { url, params },
    pageName,
    pageUrl
  } = this.props

  // Typical usage (don't forget to compare props)
  if (url !== prevProps.match.url) {
    pageUrl(url)
    pageName((params.type).replace(/-/g, " "));
  }
}

componentDidMount() {
  const {
    match: { url, params },
    pageName,
    pageUrl
  } = this.props

  pageUrl(url)
  pageName((params.type).replace(/-/g, " "));
}
1 голос
/ 05 апреля 2019

Попробуйте отправить вне рендера. вызовы с побочными эффектами должны вызываться только из componentDidMount и componentDidUpdate или из любого другого метода, который вызывается в результате взаимодействия с пользователем. Никогда внутри рендера, componentWillMount или componentWillUpdate.

ОБНОВЛЕНИЕ:

Измените компонент следующим образом:

// 
import React, { Component, Fragment } from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';

// Parts of the page
import Sidebar from './Skeleton/Sidebar';
import Content from './Skeleton/Content';
import TopBar from './Skeleton/TopBar';

// Redux
import { connect } from 'react-redux';
import { pageName, pageURL } from './../redux/actions';

class Skeleton extends Component {  

componentDidMount() {
    const { match } = this.props;
        if(match.params.type) {
          this.props.pageURL(match.url);
          this.props.pageName((match.params.type).replace(/-/g, " "));
        }
    }

  render () { 


    return (
      <Fragment>
        <CssBaseline />
        <TopBar />
        <Sidebar /> 
        <Content />
      </Fragment>
    )
  }
}

function mapStateToProps(state) {
  return {
    pageURL,
    pageName
  }
}

const mapDispatchToProps = dispatch => {
  return {
    pageName: Name => dispatch(pageName(Name)),
    pageURL: URL => dispatch(pageURL(URL)),
  }
}

export default connect(mapStateToProps, mapDispatchToProps) (Skeleton);

Следует помнить одну очень важную вещь: когда вы отправляете вызов, Redux изменяет свойства компонента, что недопустимо в методе render ().

Все вызовы, которые делают это, должны быть из обратных вызовов (например, onClick и т. Д.) Или из componentDidUpdate или componentDidMount. Никогда из componentWillUpdate или componentWillMount.

Как только вызов будет выполнен с помощью componentDidMount, свойства будут обновлены из Redux, и автоматически будет вызван вызов render (). Оттуда получите доступ к новым значениям свойств с вашей карты.

Помните, что каждый раз, когда свойство или состояние изменяется, React автоматически запускает render (), а затем вызывает componentDidUpdate (). Из-за этого при любом вызове componentDidUpdate, который обновляет состояние или свойство (через Redux), необходимо выполнить проверку, чтобы избежать бесконечных циклов.

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