Последний дочерний компонент перезаписывает все дочерние - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть родительский компонент реагирования, содержащий 3 дочерних элементов:

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

Дочерний компонент вызывает API в зависимости от значения категории проп:

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

В моем действии данныевернулся, как и ожидалось.Тем не менее, когда дочерний компонент отображает данные.Последний дочерний базис также перезаписывает свои значения в foo и bar.

A решение этой проблемы, похоже, дается здесь .Но я бы хотел, чтобы это было динамичным и зависело только от категории опоры.Разве это невозможно сделать в 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}))

}

1 Ответ

0 голосов
/ 04 декабря 2018

Вы делаете вызов API каждый раз, когда TweetColumn подключен.Если у вас есть несколько TweetColumn компонентов, и каждый из них выполняет вызов API, то в зависимости от того, какой ответ поступит последним, будет установлено значение state.tweets.items.Это потому, что вы отправляете одно и то же действие FETCH_TWEETS_SUCCESS каждый раз (последнее отменяет предыдущее).Чтобы решить эту проблему, предполагая, что ответ имеет category (foo, bar, baz), я бы написал редуктор следующим образом:

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 component:

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] существует, но вы поняли идею.

...