【发布时间】:2018-12-05 16:49:52
【问题描述】:
我有一个容器组件,它可以将数据提取到 Rails API,但无法成功迭代该数据而不会出现以下错误;
TypeError: this.state.dryRedBottles.map is not a function
这是由以下代码引起的;
render() {
let searchResults = this.state.dryRedBottles.map((bottle) => <SearchResults key={bottle} name={bottle}/>)
正如您在上面的代码中看到的那样,我设置了一个等于 this.state.dryRedBottles 上的迭代的变量,它应该将每个瓶子对象映射到演示组件 SearchResults。
我还创建了一个函数 generateSearchResults 来调试 this.props 和 this.state。 this.state.dryRedBottles 默认为空数组,但已更新为对象数组。由于 .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
我确保每个 JSON 对象都被推送到一个数组中,所以至少 this.state.dryRedBottles 会返回这个; [[{}]、[{}]、[{}]]。
我的问题是:是什么导致了这个错误? 我可以利用哪些变通方法来成功使用 searchResults?
下面是我的容器组件的全部荣耀;
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);
下面是我的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 })});
}
}
下面是我的减速器;
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;
【问题讨论】:
标签: javascript ruby-on-rails reactjs react-redux redux-thunk