简体   繁体   中英

Searching with empty value returning empty array instead of entire data in react redux

I am creating a crud web app where I have rendered all the users into the table coming from third party API. Now, I am implementing a simple search box to filter table data according to First Name . But when I start typing and write first letter, It filters out the result but when I press backspace means empty the search box, It's returning me an empty array instead of providing me the entire data.

Below is my react redux code for the same:

Component

import React from 'react';
import {connect} from 'react-redux'
import {fetchAllUsersAction,searchByUserName} from '../../redux/actions/user';

const mapStateToProps = (state) =>{
    return{
        users: state.usersData.users
    }
}

const mapDispatchToProps = (dispatch,props) =>{
    return{
        fetchUsersAction: (pageNumber) => {dispatch(fetchAllUsersAction(pageNumber))},
        searchAction: (value)=>{dispatch(searchByUserName(value))}
    }
}

class Users extends React.Component{
    render(){
        let {users} = this.props;
        return(
            <React.Fragment>
                <div className="container">
                    <div className="row mt-5">
                        <button className="btn btn-secondary" onClick={()=>this.props.fetchUsersAction(1)}>Fetch Users Data</button>

                        <input type="text" className="form-control" placeholder="Search with user name..." onChange={(e) => this.props.searchAction(e.target.value)} />
                    </div>

                    <div className="row mt-5 table-responsive">
                        <table className="table table-hover table-bordered">
                          <thead>
                            <tr>
                              <th scope="col">First Name</th>
                              <th scope="col">Last Name</th>
                              <th scope="col">Email</th>
                            </tr>
                          </thead>

                          <tbody>
                                (users.length>0)?
                                    users.map((item,index)=>(
                                        <tr key={item.id}>           
                                             <td>{item.first_name}</td>           
                                             <td>{item.last_name}</td>           
                                             <td>{item.email}</td>           
                                        </tr>
                                    ))
                                :
                                <tr>
                                  <td colSpan="7">No users found!</td>   
                                </tr>
                            }
                          </tbody>
                        </table>
                    </div>
                </div>
            </React.Fragment>            
        );
    }
}

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

Action

import {
    FETCH_ALL_USERS_SUCCESS,
    SEARCH_BY_USER_NAME
} from './action-types';

function fetchAllUsersSuccess(usersData){
    return {
        type: FETCH_ALL_USERS_SUCCESS,
        users_data: usersData
    }
}

export function fetchAllUsersAction(pageNumber) {
    return function(dispatch){
        fetch('https://reqres.in/api/users?page='+pageNumber)
            .then(res=>res.json())
            .then(json=>{
                dispatch(fetchAllUsersSuccess(json));
            })
    }
}

export function searchByUserName(value){
    return {type: SEARCH_BY_USER_NAME, value};
}

Reducer

import {
    FETCH_ALL_USERS_SUCCESS, 
    SEARCH_BY_USER_NAME
} from '../actions/action-types';


const initialState = {
    users: [] 
}

const userReducer = function(state = initialState, action) {
    switch(action.type) {
        case FETCH_ALL_USERS_SUCCESS:
            return {
                ...state,
                users: action.users_data.data
            }
        case SEARCH_BY_USER_NAME: {
              const {value} = action;
              const filtered_users = state.users.filter((val) => val.first_name.includes(value));
              return {...state, users:filtered_users};
            }                        
        default: 
            return state;
    }
}

export default userReducer;

I have removed extra code & made it extremely easy to understand. Please help me guys to know where I am stucked.

This is happening because you are updating users array with empty array when some results to empty array.

1.Store api response in users array. also in filtered array 2.on search keep updating filtered array but filter on users array 3. Render filtered array and not users array

onChange={(e) => this.props.searchAction(e.target.value)}

THIS LINE IS THE PROBLEM

First, you need to handle the change (change the state), then you need to do the action based on that state. When you call the action immediately, then you get the empty string ' '.

Here is an implementation I did using Hooks:

let { handleSearch } = props;
const [query, setQuery] = useState("");
const handleChange = e => {
setQuery(e.target.value);
};
useEffect(() => {
handleSearch(query);
}, [query]);
return (
<>
<div className="TableHeader-search">
<InputGroupAddon addonType="prepend">
<InputGroupText className="TableHeader-search__icon">
<img src={mGlass} alt="search" />
</InputGroupText>
</InputGroupAddon>
<input
className="TableHeader-search__input"
type="text"
onChange={handleChange}
placeholder={"Search..."}
name="search"
value={query}
/>
</div>
</>
);
};

Notice the onChange action does the handleChange function first... Good Luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM