How do I use this "react-filter-search" library with REDUX Actions in REACT?

How do I use this library with Redux Actions in React App?
react-filter-search

//
/*-Other Imports-*/
//
import FilterResults from 'react-filter-search';
 
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      value: ''
    };
  }
  componentWillMount() {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(response => response.json())
      .then(json => this.setState({ data: json }));
  }
  handleChange = event => {
    const { value } = event.target;
    this.setState({ value });
  };
  render() {
    const { data, value } = this.state;
    return (
      <div>
        <input type="text" value={value} onChange={this.handleChange} />
        <SearchResults
          value={value}
          data={data}
          renderResults={results => (
            <div>
              {results.map(el => (
                <div>
                  <span>{el.name}</span>
                  <span>{el.email}</span>
                </div>
              ))}
            </div>
          )}
        />
      </div>
    );
  }
}

What does the Redux store state look like?
Where are you getting the data from? (is it already in the store?)
What are you doing with the search result?

It’s not really possible to give a specific answer, because Redux is just a pattern of storing and updating the state of the data in your app. Basically, it should be very similar to the example, the
actual search and displaying of results should remain as component state, and the result (once the user has finished typing and confirmed the search has found what they want) is the thing that gets dispatched to the store.
thing that gets

Basically:

  • if the data is in the store, and when a user searches you want to update the store, then data should not be in the state, it comes from the store, then when a user finishes searching, you dispatch the result of the search to the store.
  • if the data is in the store, and when a user searches you just want to show the results in this component, then data should not be in the state, it comes from the store, and when a user finishes searching you don’t need to dispatch anything, the results are there.
  • if the data is not in the store, then the components remains basically the same, but when a user finishes searching, dispatch an action with the search result as a payload.

Assuming the data is in the store, and you want to save the search result to the store, something like:

import React from "react";
import {connect} from "react-redux";

const mapState = (state) => ({
  dataToSearch: state.dataToSearch
})

const mapDispatch = (dispatch) => ({
  dispatchSearchResult: (searchResult) =>  dispatch({type: "SEARCH_RESULT", searchResult: searchResult})
})

class Example extends React.Component {
  state = {
    searchValue: "",
    searchResult: null
  };

  handleChange = (e) => {
    this.setState({ searchValue: e.target.value})
  }

  // This means there needs to be a user action to finish searching; could use
  // onBlur or something similar instead to allow it to work silently -- you would
  // need to make decision as to how you want your UI to work.
  handleSubmit = (e) => {
    e.preventDefault();
    this.props.dispatchSearchResult(this.state.searchResult);
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          type="text"
          onChange={this.handleChange}
          value={this.state.searchValue}
        />
        <SearchResults
          value={this.state.searchValue}
          data={this.props.dataToSearch}
          renderResults={results => (
            <div>
              {results.map(el => (
                <div>
                  <span>{el.name}</span>
                  <span>{el.email}</span>
                </div>
              ))}
            </div>
          )}
        />
        <button type="submit">Submit search</button>
      </form>
    )
  }
}

export default connect(mapState, mapDispatch)(Example);
1 Like

@DanCouper Bro you are awesome…

Here’s my issue -
I need to use this react-filter-search package in my react-app, in which there’s a component that is recieving array of data from the backend received using the get call made in the actions file with axios and the res.data is made available in the state to render in tabular format.

So I would like to use this package in such a way so I can filter out the input value in the search field leaving the matched data in the table.

As per the details of this package, the author mentioned here React Filter Search

React Filter Search is simply a component that requires data in application state (needs to be an array of object s and an input value. In turn, you’ll get back…

  • filtered data based on user input
  • all data in absence of any search input

This data flows back up in the form of renderResults , which is a render prop that returns one of the above. So you’ll be responsible for setting up passing in data and an input value.
In this way, React Filter Search is unopinionated about how you store your data and how you handle user input in your application.

The magic :mage:happens in renderResults, which returns an array of objects. Your data has either been filtered based on user input, or not.

Filtering logic will iterate over any level of nesting in your data structure. Which means a good suggestion for this is something like user data or todo items that aren’t heavily nested at many levels.

To render your data, simply use .map() to render to the view–the data retains in the same structure. Return some inline JSX, or feed each element into a stateless React component that renders some UI.

Please help me solve this issue.

HERE’S THE CODE

import React, { useEffect, Fragment } from "react"
import { Link } from "react-router-dom"
import PropTypes from "prop-types"
import { getProducts } from "../../actions/product"
import { connect } from "react-redux"
import ProductList from "./ProductList"
import Loader from "../layout/Loader"
import { Table, Container, Grid } from "semantic-ui-react"

const Products = ({ getProducts, product: { products, loading } }) => {
  useEffect(() => {
    getProducts()
  }, [getProducts])

  return loading ? (
    <Loader />
  ) : (
    <Fragment>
      <Container fluid>
        <Grid>
          <Grid.Row>
            <Grid.Column width={16}>
              <div>
                {products.length > 0 ? (
                  <Table
                    color="orange"
                    celled
                    fixed
                    singleLine
                    selectable
                    className="table-responsive"
                  >
                    <Table.Header>
                      <Table.Row>
                        <Table.HeaderCell>NAME</Table.HeaderCell>
                        <Table.HeaderCell>TYPE</Table.HeaderCell>
                      </Table.Row>
                    </Table.Header>

                    <Table.Body>
                      {products.map(product => (
                        <ProductList key={product.id} product={product} />
                      ))}
                    </Table.Body>
                  </Table>
                ) : (
                  <p>No products found</p>
                )}
              </div>
            </Grid.Column>
          </Grid.Row>
        </Grid>
      </Container>
    </Fragment>
  )
}

Products.propTypes = {
  getProducts: PropTypes.func.isRequired,
  product: PropTypes.object.isRequired,
}

const mapStateToProps = state => ({
  product: state.product,
})

export default connect(
  mapStateToProps,
  { getProducts }
)(Products)

ACTIONS

import axios from "axios"
import { setAlert } from "./alert"

import {
  PRODUCT_ERROR,
  GET_PRODUCTS,
} from "./types"

// Get Products
export const getProducts = () => async dispatch => {
  try {
    const res = await axios.get(`http://HOST/product/all`)

    dispatch({
      type: GET_PRODUCTS,
      payload: res.data,
    })
  } catch (err) {
    dispatch({
      type: PRODUCT_ERROR,
      payload: { msg: err.response.statusText, status: err.response.status },
    })
  }
}

@DanCouper If possible then please help. I’m unable to solve this issue.

@DanCouper BROOOOOO I SOLVED IT. THANK YOU SOOOOOO MUUUUUUUCH :heart:

import React, { useEffect, Fragment, useState } from "react"
import { Link } from "react-router-dom"
import PropTypes from "prop-types"
import { getProducts } from "../../actions/product"
import { connect } from "react-redux"
import ProductList from "./ProductList"
import Loader from "../layout/Loader"
import { Table, Container, Grid } from "semantic-ui-react"
import FilterResults from "react-filter-search"

const Products = ({ getProducts, product: { products, loading } }) => {
  useEffect(() => {
    getProducts()
  }, [getProducts])

  const [formData, setFormData] = useState({
    value: "",
    products: [],
  })

  const { value } = formData

  const onChange = e => {
    setFormData({ ...formData, [e.target.name]: e.target.value })
  }

  return loading ? (
    <Loader />
  ) : (
    <Fragment>
      <Container fluid>
        <Grid>
          <Grid.Row>
            <Grid.Column width={16}>
              <Link to="/add_product">Add</Link>
              <input
                type="text"
                value={value}
                name="value"
                onChange={e => onChange(e)}
              />
              <div>
                {products.length > 0 ? (
                  <Table
                    color="orange"
                    celled
                    fixed
                    singleLine
                    selectable
                    className="table-responsive"
                  >
                    <Table.Header>
                      <Table.Row>
                        <Table.HeaderCell>NAME</Table.HeaderCell>
                        <Table.HeaderCell>TYPE</Table.HeaderCell>
                      </Table.Row>
                    </Table.Header>

                    <Table.Body>
                      <FilterResults
                        value={value}
                        data={products}
                        renderResults={results =>
                          results.map(product => (
                            <ProductList key={product.id} product={product} />
                          ))
                        }
                      />
                    </Table.Body>
                  </Table>
                ) : (
                  <p>No products found</p>
                )}
              </div>
            </Grid.Column>
          </Grid.Row>
        </Grid>
      </Container>
    </Fragment>
  )
}

Products.propTypes = {
  getProducts: PropTypes.func.isRequired,
  product: PropTypes.object.isRequired,
}

const mapStateToProps = state => ({
  product: state.product,
})

export default connect(
  mapStateToProps,
  { getProducts }
)(Products)

1 Like