Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setState() in React/Apollo with graphQL

I am trying to setState() to a query result I have from graphQL, but I am having difficulty finding out how to do this because it will always be loading, or it's only used from props. I first set the state

constructor (props) {
        super(props);
        this.state = { data: [] };

Then I have this query

const AllParams = gql`
    query AllParamsQuery {
        params {
            id,
            param,
            input
        }
    }`

And when it comes back I can access it with this.props.AllParamsQuery.params

How and when should I this.setState({ data: this.props.AllParamsQuery.params }) without it returning {data: undefined}?

I haven't found a way to make it wait while it's undefined AKA loading: true then setState. I've tried componentDidMount() and componentWillReceiveProps() including a async function(){...await...} but was unsuccessful, I am likely doing it wrong. Any one know how to do this correctly or have an example?

EDIT + Answer: you should not setstate and just leave it in props. Check out this link: "Why setting props as state in react.js is blasphemy" http://johnnyji.me/react/2015/06/26/why-setting-props-as-state-in-react-is-blasphemy.html There is more to the problem to update props, but some great examples can be found at this app creation tutorial: https://www.howtographql.com/react-apollo/8-subscriptions/

like image 846
Kevin Danikowski Avatar asked Sep 27 '17 20:09

Kevin Danikowski


People also ask

What is Gql in GraphQL?

Unlike traditional database query languages, GraphQL Query Language (GQL) is a projection of data returned by a root level query. The GraphQL schema will define the data model and root level queries and mutations. GQL executes those queries and defines what data to return.

Is Redux still necessary with Apollo GraphQL?

Apollo is suitable for managing remote data, and 20% of it was managed in a separate Redux Store, hence there is a need to integrate GraphQL and Redux. Apollo GraphQL no longer requires Redux. Apollo Client automatically catches the data and normalizes new data in query responses and after mutation.

Is Apollo Client a state management?

At its core, Apollo Client is a state management library that happens to use GraphQL to interact with a remote server. Naturally, some application state doesn't require a remote server because it's entirely local.


2 Answers

A simple solution is to separate your Apollo query components and React stateful components. Coming from Redux, it's not unusual to transform incoming props for local component state using mapStateToProps and componentWillReceiveProps. However, this pattern gets messy with Apollo's <Query />.

So simply create a separate component which fetches data:

...

export class WidgetsContainer extends Component {
  render (
    <Query query={GET_WIDGETS}>
      {({ loading, error, data }) => {
        if (loading) return <Loader active inline="centered" />;

        const { widgets } = data;
        return (
          <Widgets widgets={widgets} />
        )
      }}
    </Query>
  )
}

And now the Widgets components can now use setState as normal:

...
export class Widgets extends Component {
  ...
  constructor(props) {
    super()

    const { widgets } = props;
    this.state = {
      filteredWidgets: widgets
    };
  }

  filterWidget = e => {
    // some filtering logic
    this.setState({ filteredWidgets });
  }

  render() {
    const { filteredWidgets } = this.state;
    return (
      <div>
        <input type="text" onChange={this.filterWidgets} />
        {filteredWidgets.count}
      </div>
    )
  }
}
like image 153
Connor Avatar answered Sep 18 '22 17:09

Connor


What is the reason behind setting it to state? Keep in mind, Apollo Client uses an internal redux store to manage queries. If you're trying to trigger a re render based on when something changes in the query, you should be using refetchQueries(). If you absolutely need to store it in local state, I would assume you could probably compare nextProps in componentWillReceiveProps to detect when loading (the value that comes back when you execute a query from apollo client) has changed, then update your state.

like image 42
Alex K Avatar answered Sep 21 '22 17:09

Alex K