Состояние Redux Persist не сохраняется при извлечении API с использованием axios

Я получаю API с помощью axios, и действие запускается после действия «persist/REHYDRATE», что приводит к следующему: «redux-persist/autoRehydrate: 1 действия были запущены до завершения регидратации…».

Если я удаляю твит один за другим, а затем обновляю свой браузер, он не сохраняет состояние. Кажется, это не взломать..

Клиент.js

import React from 'react';
import { render } from 'react-dom';
import { Provider } from "react-redux"
import { compose, applyMiddleware, createStore } from 'redux';
import logger from "redux-logger"
import thunk from "redux-thunk"
import promise from "redux-promise-middleware"
import {persistStore, autoRehydrate} from 'redux-persist'
import tweetApp from "./reducers"
import Layout from "./components/Layout"
import { REHYDRATE } from 'redux-persist/constants'
import createActionBuffer from 'redux-action-buffer'

//const middleware = applyMiddleware(promise(), thunk, logger())
let enhancer = compose(
  autoRehydrate({ log: true }),
  applyMiddleware(
    promise(), thunk, logger(), createActionBuffer(REHYDRATE)
  )
)
const store = createStore(
  tweetApp,
  enhancer
);
const persistConfig = {
  whitelist : ["tweets"]
};
persistStore(store, persistConfig);

render(
  <Provider store={store}>
    <Layout />
  </Provider>,
  document.getElementById('app')
);

твитыReducer.js

import {REHYDRATE} from 'redux-persist/constants'

export default function reducer(state={
    tweets: [],
    fetching: false,
    fetched: false,
    error: null,
  }, action) {

    switch (action.type) {
      case "persist/REHYDRATE": {
        const incoming = action.payload.tweets; // Carts is the name of the reducer
        if (incoming) return {...state, ...incoming}
      }
      case "FETCH_TWEETS": {
        return {...state, fetching: true}
      }
      case "FETCH_TWEETS_REJECTED": {
        return {...state, fetching: false, error: action.payload}
      }
      case "FETCH_TWEETS_FULFILLED": {
        return {
          ...state,
          fetching: false,
          fetched: true,
          tweets: action.payload,
        }
      }
      case "ADD_TWEET": {
        return {
          ...state,
          tweets: [...state.tweets, action.payload],
        }
      }
      case "UPDATE_TWEET": {
        const { id, text } = action.payload
        const newTweets = [...state.tweets]
        const tweetToUpdate = newTweets.findIndex(tweet => tweet.id === id)
        newTweets[tweetToUpdate] = action.payload;

        return {
          ...state,
          tweets: newTweets,
        }
      }
      case "DELETE_TWEET": {
        return {
          tweets: [
              ...state.tweets.slice(0, action.payload),
              ...state.tweets.slice(action.payload + 1)
          ],
        }
      }
    }

    return state
}

твитыActions.js

import axios from "axios";

export function fetchTweets() {
  return function(dispatch) {
    axios.get("http://rest.learncode.academy/api/test123/tweets")
      .then((response) => {
        dispatch({type: "FETCH_TWEETS_FULFILLED",  payload: response.data})
      })
      .catch((err) => {
        dispatch({type: "FETCH_TWEETS_REJECTED", payload: err})
      })
  }
}

export function addTweet(id, text) {
  return {
    type: 'ADD_TWEET',
    payload: {
      id,
      text,
    },
  }
}

export function updateTweet(id, text) {
  return {
    type: 'UPDATE_TWEET',
    payload: {
      id,
      text,
    },
  }
}

export function deleteTweet(id) {
  return { type: 'DELETE_TWEET', payload: id}
}

layouts.js

import React from "react"
import { connect } from "react-redux"
import { fetchUser } from "../actions/userActions"
import { fetchTweets } from "../actions/tweetsActions"
import { deleteTweet } from "../actions/tweetsActions"

@connect((store) => {
  return {
    user: store.user.user,
    userFetched: store.user.fetched,
    tweets: store.tweets.tweets,
  };
})

export default class Layout extends React.Component {
  componentWillMount() {
    this.props.dispatch(fetchUser())
    this.props.dispatch(fetchTweets())
  }

  fetchTweets() {
    //this.props.dispatch(fetchTweets())
  }

  deleteTweet(idx, e) {
    this.props.dispatch(deleteTweet(idx))
  }

  render() {
    const { user, tweets, i } = this.props;
    //console.log(this.props)
    const mappedTweets = tweets.map((tweet, i) => <li key={i}>{tweet.text}<button onClick={this.deleteTweet.bind(this, i)}>delete</button></li>)

    return <div>
      <h1>{user.name}</h1>
      <ul>{mappedTweets}</ul>
    </div>
  }
}

ОБНОВЛЕНИЕ И ЖЕ ПРОБЛЕМА: я попытался заменить «componentWILLMount () на componentDidMount ()», и проблема все еще возникает. См. вывод журнала: введите здесь описание изображения


person user992731    schedule 05.02.2017    source источник


Ответы (1)


Переместите вызовы fetchTweets и fetchUser в componentDidMount, иначе весь ваш код будет выполняться синхронно: от создаваемого хранилища до создания экземпляра и рендеринга макета.

componentWillMount вызывается перед рендерингом, а componentDidMount вызывается после первого рендеринга компонента.

person CharlieBrown    schedule 05.02.2017
comment
дал, что идти и до сих пор не повезло. См. выше, я обновил ответ. - person user992731; 05.02.2017