Hseleiro Hseleiro - 1 month ago 41
React JSX Question

React-Redux - Create a Search Filter

i need help to make a Search Filter in my app. Its a simple app, used for study purposes.

The objective is to create a search filter. i have the state in search_bar container and i think i need to pass it as props to my work_list container. but i dont know how to do that. from that phase i will make it something like this.

work_list.js

renderWork() {

let filteredWorks = this.props.works.filter((work) => {
return work.title.indexOf(this.state.init) !== -1;
}
);


return filteredWorks.map((work) => {
return (
<tr>
<td>{work.title}</td>
</tr>
);
});
}


I dont know if the logic is right. Need Help.

app.js

import React, { Component } from 'react';
import SearchBar from '../containers/search_bar';
import WorkList from '../containers/work_list.js';

export default class App extends Component {
render() {
return (
<div>
<SearchBar/>
<WorkList/>
</div>
);
}
}


search_bar.js

import React, { Component } from 'react';

export default class SearchBar extends Component {

constructor(props) {
super(props);
this.state = { init: '' };
this.onInputChange = this.onInputChange.bind(this);
}

onInputChange(event) {
this.setState({ init: event.target.value });
}

onFormSubmit(event) {
event.preventDefault();
}
render() {
return (
<form
onSubmit={this.onFormSubmit}
className="input-group">
<input
className="form-control"
placeholder = "Procurar Trabalho"
onChange={this.onInputChange}
value={this.state.init} />
<span className="input-group-btn">
<button type="submit" className="btn btn-secondary">Pesquisar</button>
</span>
</form>
);
}
}


work_list.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchWork } from '../actions/index';

class WorkList extends Component {

renderWork() {
return this.props.works.map((work) => {
return (
<tr>
<td>{work.title}</td>
</tr>
);
});
}

render() {
return (
<table className="table table-hover">
<thead>
<tr>
<th>Nome</th>
</tr>
</thead>
<tbody>
{this.renderWork() }
</tbody>
</table>

);
}
}

function mapStateToProps(state) {
return {
works: state.works
}
}

export default connect(mapStateToProps)(WorkList);


My Reducers

reducer_work.js

export default function () {
return [
{ title: 'Mirististica' },
{ title: 'Vet' }
];
}


index.js

import { combineReducers } from 'redux';
import MostrarTrabalhos from './reducer_work';

const rootReducer = combineReducers({
works : MostrarTrabalhos
});

export default rootReducer;


Thank You !

Answer

It looks like your code is missing some key elements for Redux to work. You need to dispatch a Redux action when your search input changes that will in turn update the store. Right now you're merely setting the local state of SearchBar when the input changes. Secondly, your reducer doesn't modify the state, it's always returning the same array.

Something along these lines.

Your actions file might look like this:

export const SEARCH = 'SEARCH';

export function search(value) {
  return {type: SEARCH, value};
}

Then your reducer might look like this:

import {SEARCH} from './actions';

const initialState = {contents: ['Mirististica', 'Vet'], value: '', works: []};

export default function reducer(state = initialState, action) {
  switch(action.type) {
    case SEARCH: {
      const {value} = action;
      const works = state.contents.filter((val) => val.includes(value));
      return {...state, value, works};
    }
    default:
      return state;
  }
}

Then in your SearchBar:

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {search} from './actions';

class SearchBar extends Component {
  render() {
    const {search, value} = this.props;

    return (
        <input
          className="form-control"
          placeholder = "Procurar Trabalho"
          onChange={(e) => search(e.target.value)}
          value={value} />
    );
  }
} 

function mapStateToProps({works}) {
  return {value: works.value};
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({search}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);

Your WorkList component merely needs to listen for changes to works in the Redux store.

import React, { Component } from 'react';
import { connect } from 'react-redux';

class WorkList extends Component {
  render() {
    const {works} = this.props;

    return (
      <table className="table table-hover">
        <thead>
          <tr>
            <th>Nome</th>
          </tr>
        </thead>
        <tbody>{works.map((work) => <tr key={work}><td>{work}</td></tr>)}</tbody>
      </table>
    );
  }
}

function mapStateToProps({works}) {
  return {
    works: works.works
  }
}

export default connect(mapStateToProps)(WorkList);
Comments