[英]React/Redux TypeError: this.state.dryRedBottles.map is not a function
I have a container component that fetches data to a Rails API but can't successfully iterator over that data without getting the following error; 我有一个容器组件,该组件可以将数据获取到Rails API,但无法成功迭代该数据,而不会出现以下错误;
TypeError: this.state.dryRedBottles.map is not a function
This was caused by the following code; 这是由以下代码引起的;
render() {
let searchResults = this.state.dryRedBottles.map((bottle) => <SearchResults key={bottle} name={bottle}/>)
As you can see in the code above, I am setting a variable equal to an iteration over this.state.dryRedBottles, which should map every bottle object to the presentational component SearchResults. 如您在上面的代码中看到的,我在this.state.dryRedBottles上设置了一个等于迭代的变量,该变量应将每个瓶子对象映射到表示性组件SearchResults。
I also created a function, generateSearchResults to debug this.props and this.state. 我还创建了一个函数generateSearchResults来调试this.props和this.state。 this.state.dryRedBottles is by default an empty array, but it's updated to be an array of objects. 默认情况下,this.state.dryRedBottles是一个空数组,但已更新为对象数组。 Since iterators like .map or .forEach only work on arrays, I tried to mitigate this on my Rails server; 由于.map或.forEach之类的迭代器仅适用于数组,因此我尝试在Rails服务器上减轻这种情况。
def create
@wine_bottles = WineBottle.all
if params[:dryRedBottles][:fetchingRedDry] == true
@red_dry_bottles = []
@wine_bottles.each do |bottle|
if (bottle.w_type == 'red') & (bottle.dry == true)
bottle = [bottle] if !bottle.is_a?(Array)
@red_dry_bottles.push(bottle)
end
end
render json: @red_dry_bottles
else
nil;
end
end
I made sure each JSON object was push inside of an array, so at least this.state.dryRedBottles would return this; 我确保每个JSON对象都被推入数组内部,因此至少this.state.dryRedBottles将返回此值; [[{}], [{}], [{}]]. [[{}],[{}],[{}]]。
My question is: what is causing this error? 我的问题是:什么原因导致此错误? What workarounds can I leverage to successfully use searchResults? 我可以利用哪些解决方法来成功使用searchResults?
Below is my container component in its full glory; 以下是我的容器组件的全部功能;
class Red extends Component {
constructor(props) {
super(props);
this.state = {
// helps monitor toggling
redDryClick: false,
redBothClick: false,
redSweetClick: false,
fetchingRedDry: false,
fetchingRedSweet: false,
dryRedBottles: []
};
};
handleSweetRequest = (event) => {
event.preventDefault();
this.setState(prevState => ({
redDryClick: !prevState.redDryClick,
redBothClick: !prevState.redBothClick
}));
}
handleDryRequest = (event) => {
event.preventDefault();
this.setState(prevState => ({
redSweetClick: !prevState.redSweetClick,
redBothClick: !prevState.redBothClick,
fetchingRedDry: !prevState.fetchingRedDry
}));
}
componentDidUpdate(){
if (this.state.fetchingRedDry === true) {
let redDryState = Object.assign({}, this.state);
this.props.fetchDryReds(redDryState);
// this.props.dryRedBottles.length > this.state.dryRedBottles.length
if (this.props.dryRedBottles !== this.state.dryRedBottles ) {
this.setState({ dryRedBottles: this.props.dryRedBottles });
}
}
debugger;
}
handleBothRequest = (event) => {
event.preventDefault();
this.setState(prevState => ({
redDryClick: !prevState.redDryClick,
redSweetClick: !prevState.redSweetClick
}));
}
generateSearchResults = () => {
debugger;
if ( Array.isArray(this.props.dryRedBottles) ) {
this.props.dryRedBottles.map((bottle) => {
debugger;
return bottle;
})
}
}
render() {
let searchResults = this.state.dryRedBottles.map((bottle) => <SearchResults key={bottle} name={bottle}/>)
return (
<div>
<h2>Welcome to... Red</h2>
<FormControlLabel
control={
<Switch
// configuring @material-ui Switch componanet
value="hidden"
color="primary"
id="redSweet"
disableRipple
// handles previous State + redux + API call
onChange={this.handleSweetRequest}
disabled={this.state.redSweetClick}
/>
}
label="Sweet"
/>
<FormControlLabel
control={
<Switch
// configuring @material-ui Switch componanet
// value="hidden"
value="RedDry"
color="primary"
id="redDry"
disableRipple
// handles previous State + redux + API call
onChange={(event) => this.handleDryRequest(event)}
disabled={this.state.redDryClick}
/>
}
label="Dry"
/>
<FormControlLabel
control={
<Switch
// configuring @material-ui Switch componanet
value="hidden"
color="primary"
id="redBoth"
disableRipple
// handles previous State + redux + API call
onChange={this.handleBothRequest}
disabled={this.state.redBothClick}
/>
}
label="Both"
/>
<div>
{searchResults}
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
dryRedBottles: state.redWineReducer
};
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
fetchDryReds: fetchDryReds
}, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(Red);
Below is my actionCreator; 以下是我的actionCreator;
export function fetchDryReds(redDryState) {
return (dispatch) => {
// debugger;
// dispatch({ type: 'LOADING_DRY_REDS' });
return fetch('http://localhost:3001/wine_bottles', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'},
body: JSON.stringify({dryRedBottles: redDryState})})
.then(response => response.json())
.then(dryRedBottles => {
dispatch({ type: 'FETCH_DRY_REDS', dryRedBottles })});
}
}
Below is my reducer; 下面是我的减速器;
export default function redWineReducer (state={}, action) {
switch (action.type) {
case 'FETCH_DRY_REDS':
// debugger;
return action.dryRedBottles
default:
return state;
}
} }
This is the array of objects I am attempting to iterate over; 这是我尝试迭代的对象数组;
the initial state is an object... not an array so: 初始状态是一个对象...而不是数组,因此:
export default function redWineReducer (state={}, action) {
change it to: 更改为:
export default function redWineReducer (state=[], action) {
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.