react and redux: Uncaught Error: Expected the reducer to be a function
react and redux: Uncaught Error: Expected the reducer to be a function
正在阅读 udemy 教程并卡住了,出于某种原因无法弄清楚发生了什么。我浏览了我所有的代码,据我所知,与教程相比,它看起来是正确的。代码:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';
import App from './components/app';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<App />
</Provider>
, document.querySelector('.container'));
searchbar.js:
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {fetchWeather} from '../actions/index';
export default class SearchBar extends Component{
constructor(props){
super(props);
this.state = {term: ''}
this.onInputChange = this.onInputChange.bind(this)
}
onInputChange(e){
console.log(e.target.value)
this.setState({
term: e.target.value
})
}
onFormSubmit(e){
e.preventDefault()
}
render(){
return (
<form onSubmit ={this.onFormSubmit} className = "input-group">
< input
placeholder =" Get a forecast"
className = "form-control"
value = {this.state.term}
onChange = {this.onInputChange}
/>
<span className = "input-group-btn">
<button type="submit" className = "btn btn-secondary">Submit </button>
</span>
</form>
);
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({fetchWeather}, dispatch);
}
export default connect (null, mapDispatchToProps)(SearchBar);
reducers/index.js
import axios from 'axios';
const API_KEY = 'c4c2ff174cb65bad330f7367cc2a36fa'
const ROOT_URL = `http://api.openweathermap.org/data/2.5/forecast?q=appid=${API_KEY}`;
export const FETCH_WEATHER = 'FETCH_WEATHER';
export function fetchWeather(city){
let url = `${ROOT_URL}&q=${city},us`;
let request = axios.get(url);
return {
type: FETCH_WEATHER,
payload: request
};
}
app.js
import React, { Component } from 'react';
import SearchBar from '../containers/search_bar';
export default class App extends Component {
render() {
return (
<div>
<SearchBar />
</div>
);
}
}
要回答,
您的代码有点混乱,您在 reducers/index.js
中的块是您的操作,应该位于 actions/index.js
中。如前所述,您在 searchbar
组件中从那里导入它:
import {fetchWeather} from '../actions/index';
此处的 reducer 应该使用您在操作中设置的 FETCH_WEATHER
类型来更新 redux 存储的状态,因此类似于:
switch(action.type) {
case FETCH_WEATHER:
return [action.payload.data].concat(state);
}
return state;
然后要么直接导出它,要么使用 combineReducers
从 redux 到 return 一个单一的 reducer 函数(如果你有多个)。
Link 永远很棒:DOCS
正在阅读 udemy 教程并卡住了,出于某种原因无法弄清楚发生了什么。我浏览了我所有的代码,据我所知,与教程相比,它看起来是正确的。代码:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';
import App from './components/app';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<App />
</Provider>
, document.querySelector('.container'));
searchbar.js:
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {fetchWeather} from '../actions/index';
export default class SearchBar extends Component{
constructor(props){
super(props);
this.state = {term: ''}
this.onInputChange = this.onInputChange.bind(this)
}
onInputChange(e){
console.log(e.target.value)
this.setState({
term: e.target.value
})
}
onFormSubmit(e){
e.preventDefault()
}
render(){
return (
<form onSubmit ={this.onFormSubmit} className = "input-group">
< input
placeholder =" Get a forecast"
className = "form-control"
value = {this.state.term}
onChange = {this.onInputChange}
/>
<span className = "input-group-btn">
<button type="submit" className = "btn btn-secondary">Submit </button>
</span>
</form>
);
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({fetchWeather}, dispatch);
}
export default connect (null, mapDispatchToProps)(SearchBar);
reducers/index.js
import axios from 'axios';
const API_KEY = 'c4c2ff174cb65bad330f7367cc2a36fa'
const ROOT_URL = `http://api.openweathermap.org/data/2.5/forecast?q=appid=${API_KEY}`;
export const FETCH_WEATHER = 'FETCH_WEATHER';
export function fetchWeather(city){
let url = `${ROOT_URL}&q=${city},us`;
let request = axios.get(url);
return {
type: FETCH_WEATHER,
payload: request
};
}
app.js
import React, { Component } from 'react';
import SearchBar from '../containers/search_bar';
export default class App extends Component {
render() {
return (
<div>
<SearchBar />
</div>
);
}
}
要回答,
您的代码有点混乱,您在 reducers/index.js
中的块是您的操作,应该位于 actions/index.js
中。如前所述,您在 searchbar
组件中从那里导入它:
import {fetchWeather} from '../actions/index';
此处的 reducer 应该使用您在操作中设置的 FETCH_WEATHER
类型来更新 redux 存储的状态,因此类似于:
switch(action.type) {
case FETCH_WEATHER:
return [action.payload.data].concat(state);
}
return state;
然后要么直接导出它,要么使用 combineReducers
从 redux 到 return 一个单一的 reducer 函数(如果你有多个)。
Link 永远很棒:DOCS