(你可以看到我的名声不是很高:)我明白,如果你不喜欢我的问题,那将是我的最后一个,因此我会把它写成尽我所能:)
Redux loses state when navigating to another page
然而,上述问题的答案是使用' history.push',这就是我正在做的事情,我仍然遇到问题。
组件" SearchText"有一个链接到" BookResults"页。 所以,一旦" SearchText"触发动作创建者,如果(当我在控制台上看到收到结果并且状态设置有书籍列表时)我点击路由到" BookResults"的链接,我看到列表书籍。
然而,如果" SearchText"使用(当触发动作创建者时)执行新页面的history.push的回调,并且该回调由' axios(xxx)调用。然后,状态未正确设置,尽管我看到了在控制台中,HTTP请求成功。
我相信你可以看到我做错了什么(我希望它不是很愚蠢)...请告诉我。
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`}>⇐ Book Results</Link>
</form>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ searchForBooks: searchForBooks }, dispatch);
}
export default connect(null, mapDispatchToProps)(SearchText);
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;
如下所示,以下行已注释掉:
// .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
};
}
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');
}
}
答案 0 :(得分:1)
有人通过邮件向我发送了解决方案。
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 返回的值会传递给 .then 子句,以及从 .then子句返回的内容设置为结果的值。 我的错误是我没有从 .then子句返回任何内容,因此结果的值未定义,而不是返回的promise。