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

Следующий компонент React работает правильно, я могу запросить конечную точку GraphQL с помощью Apollo-React.В этом конкретном случае я использую функцию Apollo-React compose, чтобы добавить несколько запросов в один и тот же компонент.Я хотел бы вводить динамически, в поле HOC variables, userId.Есть ли способ сделать это?Поскольку простой вызов функции getUser() не работает, я получаю только обещание.

  class AllCardsScreen extends Component {

    state = {
      query: '',
      userCardsById: [],
      userId:'',
      loading: false,
    };

    getUser = async () => {
    await Auth.currentUserInfo()
      .then((data) => {
        this.setState({ userId: data.attributes.sub});
      })
      .catch(error => console.log(`Error: ${error.message}`));
    };

  render() {

    return (
      <View style={styles.container}>
        <FlatList
          data={this.props.userCardsList}
          keyExtractor={this.keyExtractor}
          renderItem={this.renderItem}
          ItemSeparatorComponent={this.renderSeparator}
          ListHeaderComponent={this.renderHeader}
          keyboardShouldPersistTaps="handled"
        />
      </View>
    );
  }


 export default compose(

  graphql(ListCards, {
    options: (props) => ({
      fetchPolicy: 'cache-and-network',
      variables: { userId : '18e946df-d3de-49a8-98b3-8b6d74dfd652'}
    }),        
    props: (props) => ({
         userCardsList: props.data.userCardsList ? props.data.userCardsList.userCards : [],

    }),
  })

  )(AllCardsScreen);

РЕДАКТИРОВАТЬ: Это окончательная рабочая версия, основанная также на предложении Даниэля (Thx Daniel), с асинхронным вызовом API, внедренным в энхансер HOC Apollo-graphQl.Мне пришлось вызвать функцию data.props.refetch(), чтобы обновить значение variables.

 class AuthWrapper extends React.Component {

    state = {
      userId: null,
    }

    async componentDidMount () {
      const data = await Auth.currentUserInfo()
      this.setState({ userId: data.attributes.sub})
    }

    render () {
      return this.state.userId
        ? <AllCardsScreen {...this.state} {...this.props}/>
        : null
    }
  }


class AllCardsScreen extends Component {

    state = {
      query: '',
      userCardsById: [],
      userId:'',
      loading: false,
    };

  componentDidMount() {
    this.props.dataRefetch(this.props.userId)
    SplashScreen.hide();
  }

  render() {

    return (
      <View style={styles.container}>
        <FlatList
          data={this.props.userCardsList}
          keyExtractor={this.keyExtractor}
          renderItem={this.renderItem}
          ItemSeparatorComponent={this.renderSeparator}
          ListHeaderComponent={this.renderHeader}
          keyboardShouldPersistTaps="handled"
        />
      </View>
    );
  }


 export default compose(

  graphql(ListCards, {
    options: (props) => ({
      fetchPolicy: 'cache-and-network',
      variables: { userId : ''}
    }),        
    props: (props) => ({
    userCardsList: props.data.userCardsList ? props.data.userCardsList.userCards : [],
    dataRefetch: (userId) => {
        props.data.refetch({userId})
       },
    }),
  })

  )(AllCardsScreen);

1 Ответ

0 голосов
/ 17 октября 2018

В graphql HOC используются только реквизиты - поскольку он фактически просто оборачивает переданный компонент, у него не будет доступа к состоянию этого компонента.Также нет способа асинхронной выборки данных в конфигурации HOC.

Самое простое решение - просто поднять состояние либо в существующий родительский компонент, либо в новый компонент, который обернет ваш существующий.Например:

class WrapperComponent extends Component {
  state = {
    userId: null,
  }

  async componentDidMount () {
    const data = await Auth.currentUserInfo()
    this.setState({ userId: data.attributes.sub})
  }

  render () {
    // May want to render nothing or a loading indicator if userId is null
    return <AllCardsScreen userId={this.state.userId} {...otherProps} />
  }
}

Кроме того, вы можете создать свой собственный HOC для инкапсуляции той же логики:

function authHOC(WrappedComponent) {
  return class AuthWrapper extends React.Component {
    state = {
      userId: null,
    }

    async componentDidMount () {
      const data = await Auth.currentUserInfo()
      this.setState({ userId: data.attributes.sub})
    }

    render () {
      return this.state.userId
        ? <WrappedComponent {...this.props} userId={this.state.userId} />
        : null
    }
  }
}
...