Reputation: 500
I have one Component which shows a list of data in a dropdown and there is an option to search these data which works as a filter. Here is my code:
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Popover from '../../Popover';
import Input from '../../Input';
import Icon from '../../Icon';
import IconButton from '../../IconButton';
const DropDownFilter = props => {
const { label, options, onChange, isSearchEnabled } = props;
const [activeOption, setActiveOption] = useState({});
const [filter, setfilter] = useState('');
const searchFilter = event => {
setfilter(event.target.value);
};
const removeFilter = () => {
setfilter('');
};
const lowercasedFilter = filter.toLowerCase();
const filteredData = options.filter(item => {
return Object.keys(item).some(
key => typeof item[key] === 'string' && item[key].toLowerCase().includes(lowercasedFilter)
);
});
const labelText = activeOption.label ? activeOption.label : label;
const handleSelectedOption = option => {
setActiveOption(option);
onChange(option);
};
return (
<div className="filter">
<Popover linkText={labelText} size="small" direction="bottom-left">
{isSearchEnabled && (
<div className="filter__search">
<Input
value={filter}
onChange={searchFilter}
preIcon={
<div role="presentation">
<Icon name="search" />
</div>
}
placeholder="Search"
postIcon={
filter.length > 0 && (
<IconButton
icon={<Icon name="close" />}
size="tiny"
onClick={removeFilter}
standalone={true}
isIconOnly={true}
/>
)
}
/>
</div>
)}
<ul className="filter__options filter__options--scrollbar">
{filteredData.map(option => (
<li
key={option.value}
role="presentation"
className={classNames('filter__options-option', {
'filter__options-option--active': option.value === activeOption.value,
})}
onClick={() => handleSelectedOption(option)}
>
{option.label}
</li>
))}
</ul>
</Popover>
</div>
);
};
DropDownFilter.defaultProps = {
label: 'Filter Menu',
options: [],
isSearchEnabled: true,
};
DropDownFilter.propTypes = {
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
options: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
})
),
onChange: PropTypes.func.isRequired,
isSearchEnabled: PropTypes.bool,
};
export default DropDownFilter;
Here is a gif of it: https://recordit.co/HtalUtuPsj
Now during searching I want to send the value of the search param to another component, the value will be used to search from a DB or any other external data source which is being handled in that new component. Such as, if I am searching for Ratings
, this component should search for it in the existing options list it has in its own component, as well as the same time it will search for Ratings
in any other external data source or DB. This external network call, search or any other functionality will be processed in the other component. So this component will only send the search param; for example Ratings
to the other component in real time.
I can think of an idea like I will get the searchParam in a state and pass the setState value to a new props which will be called through an onSearchParamChange function, this new function will pass the data through a callback and the other component will get the data through calling that props of this component. I am not sure if this is the correct way and also I am not able to implement this thought in the code either. Is there any better way to do it? if so what would be that coding implementation?
Upvotes: 0
Views: 290
Reputation: 983
If you need to pass to a parent component you should be able to use for example the onChange
prop which is passed to your component, like you are doing in the handleSelectedOption
function. That function is in fact passing the chosen option to the parent component. If you want to pass to the parent component when the user is typing, then you should call the onChange
function also in searchFilter
:
const searchFilter = event => {
const option = event.target.value);
setfilter(option);
onChange(option);
};
If you want to pass it to a child component, the you can just pass it as prop:
<ChildComponent filter={ filter } />
Upvotes: 1