我在我的React应用程序中使用redux。我试图从我的减速器中获取数据,但是当我试图这样做时。我遇到一些错误。
未捕获的错误:减速器已采取行动“ RECEIVE_CATEGORY_NAME” “ categoriesReducer”返回未定义。要忽略某个动作,您必须 明确返回先前的状态。如果您希望该减速器固定 没有值,您可以返回null而不是未定义。
在influencersNameReducer的情况下,编写的逻辑工作正常,但显示类别Reducer错误 home_reducer.js
import { RECEIVE_INFLUENCERS_NAME, RECEIVE_CATEGORY_NAME } from './home_actions';
export const influencersNameReducer = (state = [], { type, influencers }) => {
console.log(influencers)
return type === RECEIVE_INFLUENCERS_NAME ? influencers : state
}
export const categoriesReducer = (state = [], { type, category }) => {
console.log(type, category)
return type === RECEIVE_CATEGORY_NAME ? category : state
}
home_actions.js
export const RECEIVE_INFLUENCERS_NAME = 'RECEIVE_INFLUENCERS_NAME'
export const RECEIVE_CATEGORY_NAME = 'RECEIVE_CATEGORY_NAME';
const receiveInfluencersName = influencers => ({ type: RECEIVE_INFLUENCERS_NAME, influencers })
const receiveCategoryName = categories => ({ type: RECEIVE_CATEGORY_NAME, categories })
export const fetchInfluencers = _ => dispatch => {
$.ajax({
method: 'get',
url: 'vip_api/influencers',
data: { name: _ },
success(influencers) {
dispatch(receiveInfluencersName(influencers))
},
error({ responseJSON, statusText }) {
dispatch(receiveServerErrors(responseJSON || [statusText]))
}
})
}
export const fetchCategories = _ => dispatch => {
$.ajax({
method: 'get',
url: 'vip_api/categories',
data: { name: _ },
success(categories) {
dispatch(receiveCategoryName(categories))
},
error({ responseJSON, statusText }) {
dispatch(receiveServerErrors(responseJSON || [statusText]))
}
})
}
store.js
import {influencersNameReducer, categoriesReducer} from './Vvip/Home/home_reducer';
import { composeWithDevTools } from 'redux-devtools-extension';
const reducer = combineReducers({
categoriesReducer,
influencersNameReducer,
})
const composeEnhancers = composeWithDevTools({
// Specify name here, actionsBlacklist, actionsCreators and other options if needed
});
export default (state = {}) => (
createStore(reducer, state, composeEnhancers(applyMiddleware(errorMiddleware, timeoutMiddleware, thunk)))
)
index.js
import React, { Component } from 'react'
import Select, { components } from 'react-select'
import DateRange from '../../shared/_date_range';
import moment from 'moment';
import {ethnicities, ageRanges, isoCountries} from '../../constants';
import { connect } from 'react-redux';
import {fetchInfluencers, fetchCategories} from './home_actions';
class InfluencersForm extends Component {
constructor() {
super();
this.state = {
demography: null,
dates : {
startDate: moment(),
endDate: moment()
},
influencersName: [],
}
}
handleInfluencerName = event => {
this.props.dispatch(fetchInfluencers(event))
}
handleSelectedInfluencer = event => {
console.log(event)
this.setState({
isMenuOpenInfluencer : false
})
}
componentWillReceiveProps(newProps) {
console.log(newProps);
if (newProps.influencersNameReducer && newProps.influencersNameReducer.length) {
this.setState({
influencersName: newProps.influencersNameReducer.map((influencer, index) => {
return ({ value: influencer, label: influencer })
}),
})
}
}
handleInfluencerType = event => {
console.log(event)
}
handleInfluencerCountry = event => {
console.log(event)
}
handleInfluencerSubscribers = event => {
console.log(event)
}
handleInfluencerVideosCreated = event => {
console.log(event)
}
handleInfluencerCategory = event => {
console.log(event)
this.props.dispatch(fetchCategories(event))
}
onDemographyChange = event => {
console.log(event.currentTarget.value)
this.setState({
demography: event.currentTarget.value
})
}
handleInfluencerAge = event => {
console.log(event)
}
handleInfluencerGender = event => {
console.log(event)
}
handleInfluencerEthnicity = event => {
console.log(event)
}
updateDates = event => {
console.log(event)
this.setState({
dates: event
})
}
render() {
const influencersType = [
{ value: 'a', label: 'Type A' },
{ value: 'b', label: 'Type B' },
{ value: 'c', label: 'Type C' }
]
const influencersCategory = [
{ value: 'a', label: 'Type A' },
{ value: 'b', label: 'Type B' },
{ value: 'c', label: 'Type C' }
]
const influencersAge = ageRanges.map(age => ({ value: age, label: age }))
const influencersGender = [
{ value: 'male', label: 'Male' },
{ value: 'female', label: 'Female' }
]
const influencersKeywords = [
{ value: 'youtuber', label: 'Youtuber' },
{ value: 'vlogger', label: 'Vlogger' }
]
const influencersCountry = Object.keys(isoCountries).map(code => ({ value: code, label: isoCountries[code] }))
const DropdownIndicator = (props) => {
return components.DropdownIndicator && (
<components.DropdownIndicator {...props}>
<i className="fa fa-search" aria-hidden="true" style={{ position: 'initial', color: 'black' }}></i>
</components.DropdownIndicator>
);
};
return (
<div className='home-forms influencer-form'>
<div className='display-flex'>
<Select
options={this.state.influencersName}
onChange={this.handleSelectedInfluencer}
closeMenuOnSelect = {true}
isSearchable={true}
components={{ DropdownIndicator }}
onInputChange = {this.handleInfluencerName}
placeholder={'Start Typing Influencers Name'}
classNamePrefix="vyrill"
className="influencers influencers-icon-name" />
<Select
options={influencersType}
onChange={this.handleInfluencerType}
placeholder='Type of Influencers'
classNamePrefix="vyrill"
className="influencers influencers-icon-type" />
<Select
options={influencersCountry}
onChange={this.handleInfluencerCountry}
isSearchable={true}
components={{ DropdownIndicator }}
placeholder='Start Typing Country'
classNamePrefix="vyrill"
className="influencers influencers-icon-country" />
</div>
<div className='display-flex' style={{ marginTop: 32 }}>
<Select
options={influencersType}
onChange={this.handleInfluencerSubscribers}
placeholder='Number of Subscribers'
classNamePrefix="vyrill"
className="influencers influencers-icon-type" />
<Select
options={influencersType}
onChange={this.handleInfluencerVideosCreated}
placeholder='Number of Videos Created'
classNamePrefix="vyrill"
className="influencers influencers-icon-videos-created" />
<Select
options={influencersCategory}
onChange={this.handleInfluencerCategory}
onInputChange = {this.handleInfluencerCategory}
isSearchable={true}
components={{ DropdownIndicator }}
placeholder='Start Typing Category'
classNamePrefix="vyrill"
className="influencers influencers-icon-country influencers-icon-category" /> {/* remove influencers-icon-country later */}
</div>
<div style={{ marginTop: 50 }}>
<div className="display-flex">
<div className="icon-subscribers" style={{ marginTop: 4 }}></div>
<div style={{ fontWeight: 700, marginTop: 4 }}>Demographics</div>
<div className="radio-container">
<label>
<div style={{ fontSize: 14, marginTop: 4 }}>By influencers</div>
<input
type="radio"
name="demographics"
value="influencers"
checked={this.state.demography === 'influencers'}
onChange={this.onDemographyChange} />
<span className="custom-radio">
</span>
</label>
</div>
<div className="radio-container">
<label>
<div style={{ fontSize: 14, marginTop: 4 }}>By people in videos</div>
<input
type="radio"
name="demographics"
value="people in videos"
checked={this.state.demography === 'people in videos'}
onChange={this.onDemographyChange} />
<span className="custom-radio"></span>
</label>
</div>
</div>
</div>
<div className="display-flex" style={{ marginTop: 40 }}>
<Select
options={influencersAge}
onChange={this.handleInfluencerAge}
placeholder='Age'
classNamePrefix="vyrill"
className="influencers" />
<Select
options={influencersGender}
onChange={this.handleInfluencerGender}
placeholder='Gender'
classNamePrefix="vyrill"
className="influencers" />
<Select
options={ethnicities}
onChange={this.handleInfluencerEthnicity}
placeholder='Ethnicity'
classNamePrefix="vyrill"
className="influencers" />
</div>
<div style={{marginTop: 50}}>
<div style={{display: 'inline'}}>Contains keywords (in transcript):</div>
<span className="icon-info"></span>
<Select
options={influencersKeywords}
onChange={this.handleInfluencerName}
isSearchable={true}
classNamePrefix="vyrill"
placeholder= {" "}
className="influencers influencers-keywords"
styles = {{marginTop: 10}}/>
</div>
<div style={{marginTop: 50}} className="date-picker">
<div>Posted content time range</div>
<DateRange dates={ this.state.dates } updateDates={ this.updateDates }/>
<div className="icon-arrow-right"></div>
</div>
</div>
)
}
}
const mapStateToProps = ({ influencersNameReducer, categoriesReducer }) => ({
influencersNameReducer,
categoriesReducer
})
export default connect(mapStateToProps)(InfluencersForm)
答案 0 :(得分:0)
您需要将减速器修改为:
export const influencersNameReducer = (state = [], { type, influencers }) => {
switch(type) {
case RECEIVE_INFLUENCERS_NAME:
return influencers;
default:
return state;
}
}
export const categoriesReducer = (state = [], { type, category }) => {
switch(type) {
case RECEIVE_CATEGORY_NAME:
return category;
default:
return state;
}
}
在每一个动作上,调度员都去往每个减速器。由于在您的代码中influencersNameReducer
减速器对RECEIVE_CATEGORY_NAME
类型没有执行任何操作,因此返回undefined。所以你得到了错误。使用开关盒是实现此目的的方法。