最后一个子组件覆盖所有子组件



我有一个包含3个子级的父级react组件:

<ChildComponent category="foo" />
<ChildComponent category="bar" />
<ChildComponent category="baz" />

子组件根据道具类别值调用api:

http://example.com/listings.json?category=foo

在我的操作中,数据会按预期返回。但是,当子组件渲染数据时。最后一个子baz在foo和bar中也覆盖了它的值。

这里似乎给出了这个问题的解决方案。但我希望这是动态的,只取决于类别道具。这在Redux不可能做到吗?

我的子组件如下所示:

class TweetColumn extends Component {
componentDidMount() {
this.props.fetchTweets(this.props.column)
}
render() {
const { tweets, column } = this.props
if (tweets.length === 0) { return null }
const tweetItems = tweets[column].map(tweet => (
<div key={ tweet.id }>
{ tweetItems.name }
</div>
)
return (
<div className="box-content">
{ tweetItems }
</div>
)
}
}
TweetColumn.propTypes = {
fetchTweets: PropTypes.func.isRequired,
tweets: PropTypes.array.isRequired
}
const mapStateToProps = state => ({
tweets: state.tweets.items
})
export default connect(mapStateToProps, { fetchTweets })( TweetColumn )

减速器

export default function tweetReducer(state = initialState, action) {
switch (action.type) {
case FETCH_TWEETS_SUCCESS:
return {
...state,
[action.data[0].user.screen_name]: action.data
}
default:
return state;
}
}
export default combineReducers({
tweets: tweetReducer,
})

操作:

export const fetchTweets = (column) => dispatch => {
dispatch({ type: FETCH_TWEETS_START })
const url = `${ TWITTER_API }/statuses/user_timeline.json?count=30&screen_name=${ column }`
return axios.get(url)
.then(response => dispatch({
type: FETCH_TWEETS_SUCCESS,
data: response.data
}))
.then(response => console.log(response.data))
.catch(e => dispatch({type: FETCH_TWEETS_FAIL}))
}

每次挂载TweetColumn时,都会进行一次api调用。如果您有多个TweetColumn组件,并且每个组件都进行一个api调用,那么最后到达的响应将设置state.tweets.items的值。这是因为您每次都在调度相同的操作FETCH_TWEETS_SUCCESS(最后一个操作将覆盖前一个操作(。为了解决这个问题,假设响应有一个category(foo,bar,baz(,我会用以下方式编写reducer:

export default function tweetReducer(state = initialState, action) {
switch (action.type) {
case FETCH_TWEETS_SUCCESS:
return {
...state,
[action.data.category]: action.data
}
default:
return state;
}
}

然后,您可以在TweetColumn组件中执行以下操作:

class TweetColumn extends Component {
componentDidMount() {
this.props.fetchTweets(this.props.column)
}
render() {
const { column } = this.props;
const tweetItems = this.props.tweets[column].map(tweet => (
<div key={ tweet.id }>
{ tweet.name }
</div>
)
return (
<div className="box-content">
{ tweetItems }
</div>
)
}
}
const mapStateToProps = state => ({
tweets: state.tweets
})
const mapDispatchToProps = dispatch => ({
fetchTweets: column => dispatch(fetchTweets(column))
})
export default connect(
mapStateToProps,
mapDispatchToProps,
)( TweetColumn )

您必须进行一些验证以确保tweets[column]存在,但您已经明白了。

最新更新