next.js mapStateToProps, mapDispatchToProps и getInitialProps - PullRequest
0 голосов
/ 25 сентября 2018

В настоящее время я все еще пытаюсь обернуть голову вокруг редукса при использовании next.js, и я не уверен, как лучше всего использовать редукс с next.Я привык использовать mapDispatchToProps для своих действий и mapStateToProps для своих реквизитов.После некоторых исследований я теперь использую next-redux-wrapper в своих _app.js, как рекомендовано, но сейчас я борюсь с тем, как наилучшим образом получить мои реквизиты и распределить свои действия.Я рассмотрел несколько примеров и приемов и теперь имею счетчик, основанный на одном из этих примеров.

class Counter extends Component {
  increment = () => {
    const {dispatch} = this.props
    dispatch(incrementCount())
  }

  decrement = () => {
    const {dispatch} = this.props
    dispatch(decrementCount())
  }

  reset = () => {
    const {dispatch} = this.props
    dispatch(resetCount())
  }

  render () {
    const { count } = this.props
    return (
      <div>
        <h1>Count: <span>{count}</span></h1>
        <button onClick={this.increment}>+1</button>
        <button onClick={this.decrement}>-1</button>
        <button onClick={this.reset}>Reset</button>
      </div>
    )
  }
}

function mapStateToProps (state) {
  const {count} = state.counter;
  return {count};
}

export default connect(mapStateToProps)(Counter)

Большинство примеров, которые я видел до сих пор, делают что-то похожее на это или только действия диспетчеризации в getInitialProps.Есть ли причина сделать это таким образом и не использовать mapDispatchToProps?

Потому что эта работа также прекрасно работает:

export default connect(null, {authenticate})(Signin);

Кажется, что диспетчеризация действий в getIntialProps имеет некоторый недостаток (или я допустил некоторые ошибки), потому что они не выполняются снова, когда реквизитыменять.В моем компоненте профиля пользователя я получаю текущего пользователя на основе токена из магазина приставок, например, так:

const Whoami = ({isAuthenticated, user}) => (
  <Layout title="Who Am I">
    {(isAuthenticated && user && <h3 className="title is-3">You are logged in as <strong className="is-size-2 has-text-primary">{user}</strong>.</h3>) ||
      <h3 className="title is-3 has-text-danger ">You are not authenticated.</h3>}
  </Layout>
);

Whoami.getInitialProps = async function (ctx) {
  initialize(ctx);

  const token = ctx.store.getState().auth.token;
  if(token) {
    const response = await axios.get(`${API}/user`, {headers: {
      authorization: token
    }});
    const user = response.data.user;
    return {
      user
    };
  }
    }

const mapStateToProps = (state) => (
  {isAuthenticated: !!state.auth.token}
);

export default connect(mapStateToProps)(Whoami);

Это прекрасно работает для начальной загрузки страницы или при перемещении туда одного клиента, нокогда срок действия токена истекает или я выхожу, страница не отражает это без перезагрузки или перехода туда снова без моего mapStateToProps.Но кажется неуклюжим разделить заботу о двух отдельных функциях.Но я не могу найти более чистый способ сделать это.

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Я нашел некоторые ответы на свои вопросы после того, как немного поигрался со следующим.Для страниц, на которых данные не изменяются после первоначальной загрузки, я мог бы избавиться от mapStateToProps, переписав свои thunks немного, чтобы вернуть диспетчеризацию, и использовать getInitialProps только так:

export function fetchShow(id) {
  return (dispatch) => {
      dispatch({ type: actionTypes.FETCH_SHOW_REQUESTED,id});
      // we need to return the fetch so we can await it
      return fetch(`http://api.tvmaze.com/shows/${id}`)
          .then((response) => {
              if (!response.ok) {
                  throw Error(response.statusText);
              }
              //dispatch(itemsIsLoading(false));
              return response;
          })
          .then((response) => response.json())
          .then((data) =>      dispatch({type: actionTypes.FETCH_SHOW_SUCEEDED,id, show: data, time: Date.now() }))
          .catch(() => dispatch({ type: actionTypes.FETCH_SHOW_ERROR,id }));
  };
}

Post.getInitialProps = async function ({store, isServer, pathname, query}) {
  const { id } = query;
  const {show} = await store.dispatch(fetchShow(id));
  return {show};
}

Для страниц, где данные должныобновлять информацию об изменениях в магазине я пока не уверен.Моя текущая идея - попытаться написать вспомогательную функцию, которая будет вызываться из getInitialProps и mapStateToProps, чтобы уменьшить дублирование кода, но я пока не уверен.

0 голосов
/ 25 сентября 2018

О mapDispatchToProps:

Лучше использовать mapDispatchToProps хотя бы потому, что это проще для тестирования: вы можете просто передать фиктивную функцию вашему компоненту.С использованием this.props.dispatch для отправки некоторых импортированных действий это может быть намного сложнее.

О getInitialProps:

Этот ответ может быть полезен:

GetInitialProps: предоставляется Next.js, и он НЕ всегда срабатывает, поэтому будьте осторожны с этим, это происходит, когда вы оборачиваете один компонент в другой.Если родительский Компонент имеет GetInitialProps, дочерний GetInitialProps никогда не сработает, для получения дополнительной информации см. этот поток .

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