Redux 在使用 react-router 'history.push'导航到另一个页面时丢失状态



(因为您可以看到我的声誉不是很高:),我知道,如果您不喜欢我的问题,那将是我的最后一个,因此我我会尽可能地写它:)

我面临的问题与:

redux导航到另一页

但是,上述问题的答案是使用" history.push",这是我在做的事情,我仍然有问题。

我正在使用:

  • "反应":"^16.0.0"
  • " react-redux":"^5.0.6"
  • " React-Router":"^4.2.0"
  • " react-router-dom":"^4.2.2"
  • " redux":"^3.7.2"
  • " redux-promise":"^0.5.3"
  • " axios":"^0.17.1"

我正在做以下操作:

  1. 在一个反应组件中,"搜索文本",获取文本字符串并调用动作创建者
  2. 在动作创建者中,使用文本字符串将HTTP请求发送到GoodReads.com
  3. 在我的还原器中,使用动作有效载荷设置redux状态
  4. 使用另一个组件" BookResults"(在另一个路线中),以显示此状态

组件" searchText"具有指向" BookResults"页面的链接。因此,一旦"搜索文本"发射了动作创建者,如果(当我在控制台上看到结果被收到结果并用书籍列表设置状态时),我单击路由到" BookResults"的链接,我会看到书籍清单。

但是,如果"搜索文本"使用(触发动作创建者时)执行"历史记录"的回调。正确地,尽管我在控制台中看到HTTP请求成功。

我确定您可以看到我做错了什么(我希望这不是很愚蠢)...请告诉我。

这是代码:

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';
import SearchText from './components/search_text';
import BookResults from './components/book_results';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <BrowserRouter>
    <div>
      <BrowserRouter>
        <Switch>
          <Route path="/book_results" component={BookResults} />
          <Route path="/" component={SearchText} />
        </Switch>
      </BrowserRouter>
    </div>
    </BrowserRouter>
  </Provider>
  , document.querySelector('#root'));

搜索文本组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router-dom';
import { searchForBooks } from '../actions';
class SearchText extends Component {
    constructor(props) {
        super(props);
        this.state = {
            searchText: ''
        };
        this.handleFormSubmit = this.handleFormSubmit.bind(this);
        this.handleSearchTextChange = this.handleSearchTextChange.bind(this);
    }
    handleSearchTextChange(e) {
        this.setState({ searchText: e.target.value });
    }
    handleFormSubmit(e) {
        e.preventDefault();
        const formPayload = {
            searchText: this.state.searchText
        };
        console.log("In SearchBooks/handleFormSubmit. Submitting. state: ", this.state);
    this.props.searchForBooks(formPayload, () => {
            this.props.history.push(`/book_results`);
        });
    }
    render() {
        return (
            <form className="container" onSubmit={this.handleFormSubmit}>
                <h3>Search Form</h3>
                <div className="form-group">
                    <label className="form-label">{'Search Text:'}</label>
                    <input
                        className='form-input'
                        type='text'
                        name='searchText'
                        value={this.state.searchText}
                        onChange={this.handleSearchTextChange}
                        onBlur={this.handleSearchTextBlur}
                        placeholder='' />
                </div>
                <br />
                <input
                    type="submit"
                    className="btn btn-primary float-right"
                    value="Submit"/>
                <br /><br />
                <Link to={`/book_results`}>&lArr; Book Results</Link>
            </form>
        );
    }
}
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ searchForBooks: searchForBooks }, dispatch);
}
export default connect(null, mapDispatchToProps)(SearchText);

bookResults组件

import React from 'react';
import { connect } from 'react-redux';
import _ from 'lodash';
import Book from './book';
class BookResults extends React.Component {
  render() {
    let books;
    const booksArray = _.values(this.props.bookResults);
    console.log("***In BookResults. booksArray: ", booksArray);
    if (booksArray.length === 0) {
      books = "No books to display";
    } else {
      books = booksArray.map( (book) => {
        return (
          <Book book={book} key={book.id} />
        );
      });
    }
    return (
      <div>
        <h2>Search Results</h2>
        <br />
        <ul>
          {books}
        </ul>
      </div>
    );
  }
}
function mapStateToProps(state) {
  return {
    bookResults: state.bookResults,
    cats: state.cats
  };
}
export default connect(mapStateToProps)(BookResults);

书籍组件

import React from 'react';
const Book = (props) => (
  <li>
    {props.book.title}
  </li>
);
export default Book;

actions/index.js

如下所示,以下行评论出来:

//  .then(() => callback());

如果包括它,我有问题。

import axios from 'axios';
export const SEARCH_FOR_BOOKS = 'search_for_books';
const GOODREADS = "https://www.goodreads.com/search/index.xml";
const KEY = "xxx";
export function searchForBooks(values, callback) {
  let result;
  console.log("In actions/searchForBooks. values: ", values);
  if (!values.searchText || values.searchText === "") {
    console.error("*** ERROR *** In actions/searchForBooks." +
    "values.searchText: ", values.searchText);
  } else {
    const searchUrl = `${GOODREADS}?key=${KEY}&q=${values.searchText}`;
    console.log("In actions/searchForBooks. url: " + searchUrl);
    result = axios.get(searchUrl);
    //  .then(() => callback());
  }
  return {
    type: SEARCH_FOR_BOOKS,
    payload: result
  };
}

reducers/index.js

import { combineReducers } from 'redux';
import bookResultsReducer from './reducer_book_results';
const rootReducer = combineReducers({
  bookResults: bookResultsReducer
});
export default rootReducer;

还原

import { parseString } from  'xml2js';
import _ from 'lodash';
import { SEARCH_FOR_BOOKS } from '../actions/index';
const bookResults = {};
export default function bookResultsReducer(state = bookResults, action) {
  switch (action.type) {
    case SEARCH_FOR_BOOKS:
      console.log("In bookResultsReducer. payload: ", action.payload);
      if (action.error) {  // error from goodreads search books
        console.error("*** APP ERROR *** In bookResultsReducer. action.error: ", action.error);
      } else if (!action.payload || !action.payload.data) {
        console.error("*** APP ERROR *** In bookResultsReducer." +
        " action.payload or action.payload.data is undefined", action.payload);
      } else {
        parseString(action.payload.data, function(err, result) {
          if (err) {
            console.error("*** APP ERROR *** In bookResultsReducer. Error from parseString: ", err);
          } else {
            state = Object.assign({}, getBooks(result));
          }
        });
      }
      console.log("In bookResultsReducer. new state: ", state);
      return state;
      break;
    default:
      return state;
  }
}
function getBooks(data) {
  const bookResults =  data.GoodreadsResponse.search[0].results[0].work;
  if (!bookResults || bookResults.length === 0) {
    return {};
  } else {
    const results = bookResults.map( (book, index) => {
      const bookInfo = book.best_book[0];
      return (
        { id: index + 1,
          title: bookInfo.title[0] }
      );
    });
    return _.mapKeys(results, 'id');
  }
}

有人通过邮件发送了我的解决方案。

错误是在action/index.js文件中。

而不是:

import axios from 'axios';
export const SEARCH_FOR_BOOKS = 'search_for_books';
const GOODREADS = "https://www.goodreads.com/search/index.xml";
const KEY = "xxx";
export function searchForBooks(values, callback) {
  let result;
  console.log("In actions/searchForBooks. values: ", values);
  if (!values.searchText || values.searchText === "") {
    console.error("*** ERROR *** In actions/searchForBooks." +
    "values.searchText: ", values.searchText);
  } else {
    const searchUrl = `${GOODREADS}?key=${KEY}&q=${values.searchText}`;
    console.log("In actions/searchForBooks. url: " + searchUrl);
    result = axios.get(searchUrl)
      .then(() => callback());
  }
  return {
    type: SEARCH_FOR_BOOKS,
    payload: result
  };
}

我应该写信:

import axios from 'axios';
export const SEARCH_FOR_BOOKS = 'search_for_books';
const GOODREADS = "https://www.goodreads.com/search/index.xml";
const KEY = "xxx";
export function searchForBooks(values, callback) {
  let result;
  console.log("In actions/searchForBooks. values: ", values);
  if (!values.searchText || values.searchText === "") {
    console.error("*** ERROR *** In actions/searchForBooks." +
    "values.searchText: ", values.searchText);
  } else {
    const searchUrl = `${GOODREADS}?key=${KEY}&q=${values.searchText}`;
    console.log("In actions/searchForBooks. url: " + searchUrl);
    result = axios.get(searchUrl)
      .then((res) => {
        callback();
        return res;
      });
  }
  return {
    type: SEARCH_FOR_BOOKS,
    payload: result
  };
}

说明:

问题是从 axios.get 返回的值传递给.。strong>设置为结果的值。我的错误是,我没有从>。然后从句返回任何内容,因此 result 的值是未定义的,而不是返回的承诺。

相关内容

最新更新