Search code examples
djangoreactjsgraphqlapollo

How to filter elements using React, Graphql and Apollo with es6


I have a React project with a GraphQL using Apollo client. I am trying to figure out how to change the query result based on search text. I implemented query search in backend and its working perfectly. But I dont know how to set up filter in React using that same query. Despite there is tutotial on how to filter on https://www.howtographql.com/react-apollo/7-filtering-searching-the-list-of-links/, it doesnt use ES6 and I literaly dont know how to do it. Im stuck on this filter around 10 days.

I will show you my code.

App.js

import React from 'react';
import HeroesDota from './components/HeroesDota';
import Search from './components/HeroSearch'

import { ApolloProvider } from '@apollo/react-hooks';

import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";


const cache = new InMemoryCache();
const link = new HttpLink({
  uri: "http://localhost:8000/graphql/"
});

const client = new ApolloClient({
  cache,
  link
});


const App = () => {

return (
    <ApolloProvider client={client}>
      <Search />
      <HeroesDota />
    </ApolloProvider>
)};

export default App;

HeroesDota.js (compoenent)

import React from 'react'
import gql from "graphql-tag";
import { useQuery } from '@apollo/react-hooks';
import '../index.css'
import styled from 'styled-components';

const Images = styled.img`
    margin:0;
    border: 3px solid #288eea;
    display: inline;
    width: 90px;
    height: 50px;
`
const HEROES_DOTA2 = gql`
    query {
        heroes {
            name
            heroType
            image
        }
    }
`;


const HeroesDota = () => {
    const { loading, error, data } = useQuery(HEROES_DOTA2);

    if (loading) return <p>Loading...</p>;
    if (error) return <p>Error :(</p>;

    return data.heroes.map(({name, heroType, image }) => (
      <div className="row" key={Math.random() + 1}>
        <div className="column">
          <button className="button-hero"><Images className="hero_images" src= {`${image}`} alt={name}></Images></button>
            <div className="hero_info">{name} - {heroType}</div>
        </div>
      </div>

    ));
}

export default HeroesDota;

HeroSearch.js (compoenent that doesnt work as I expected)

import React, { useState } from 'react'
import gql from "graphql-tag";
import { withApollo } from 'react-apollo'
import Hero from './HeroesDota'
import '../index.css'

 const SEARCH_HEROES = gql`
     query ($search: String) {
         heroes (search: $search) {
             id
             name
         }
     }
 `;

const Search = () => {

    const [heroes, setHeroes] = useState([])
    const [search, setSearch] = useState('')


    const _executeSearch = async () => {
        const { search } = search
        const result = await this.props.client.query({
          query: SEARCH_HEROES,
          variables: { search },
        })
        const heroes = result.data.heroes.name
        setHeroes({ heroes })
    }

    return (
        <div>
          <div>
            Search
            <input
              type='text'
              onChange={e => setSearch({ search: e.target.value })}
            />
            <button onClick={() => _executeSearch()}>OK</button>
          </div>
          {heroes.map((hero, index) => (
            <Hero key={hero.id} hero={hero} index={index} />
          ))}
        </div>
      )
    }

export default withApollo(Search)

After U oress OK button to exectue search i get following error. Unhandled Rejection (ReferenceError): Cannot access 'search' before initialization.

If I try to do something similar like I did in Component HeroesDota i still cant make it.

Does anyone know how to filter query in React using es6, not class based compoenent like they did on this tutorial.

Thanks


Solution

  • const Search = (props) => {
        props.client.query()
        ...
    }
    

    or

    const Search = ({ client }) => {
        client.query()
        ...
    }
    

    Although I would also recommend you use the the new hooks syntax.