so im trying to implement a search box with useState and useEffect. we have an array of objects and want to filter it according to our search term. here is my implementation:
import React, {useEffect, useState} from "react";
const array = [
{ key: '1', type: 'planet', value: 'Tatooine' },
{ key: '2', type: 'planet', value: 'Alderaan' },
{ key: '3', type: 'starship', value: 'Death Star' },
{ key: '4', type: 'starship', value: 'CR90 corvette' },
{ key: '5', type: 'starship', value: 'Star Destroyer' },
{ key: '6', type: 'person', value: 'Luke Skywalker' },
{ key: '7', type: 'person', value: 'Darth Vader' },
{ key: '8', type: 'person', value: 'Leia Organa' },
];
let available = []
const Setup = () => {
const [state, setState] = useState('');
useEffect(() => {
available = array.filter(a => a.value.startsWith(state));
},[state])
const show = state ? available : array;
return <>
<input value={state} onChange={e => setState(e.target.value)} type="text" className="form"/>
{show.map(a => {
return <Data id={a.key} key={parseInt(a.key)} value={a.value} type={a.type}/>
})}
</>
}
const Data = (props) => {
return <>
<div>
<p>{props.value}</p>
</div>
</>
}
export default Setup;
the problem starts when we give our search box a valid search term(like 'T'). i expect it to change the output accordingly(to only show 'Tatooine') but the output does not change.
meantime if you add another character to search term(like 'a' which would set our search term to 'Ta') it will output the expected result. in the other words, search term is not applied synchronously. do you have any idea why is that
The useEffect hook is triggered when the component mounts, rerenders or unmounts. In your case, the change of the search field causes a rerender because of the change of the state. This results in your useEffect triggering after the state change and is too late for what you need.
If you type "Ta" into your field, you'll see it works, but it appears as if the search is one step behind.
You can simply remove the use of useEffect and filter when you render. This means you can also remove the whole logic around the available and show variables:
const Setup = () => {
const [state, setState] = useState("");
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{array
.filter((a) => a.value.startsWith(state))
.map((a) => (
<Data
id={a.key}
key={parseInt(a.key, 10)}
value={a.value}
type={a.type}
/>
))}
</>
);
};
There is some good information in the Using the Effect Hook docs.
You just add toLowerCase mehtod to your filter function. just like this :
import React, { useEffect, useState } from "react";
const array = [
{ key: "1", type: "planet", value: "Tatooine" },
{ key: "2", type: "planet", value: "Alderaan" },
{ key: "3", type: "starship", value: "Death Star" },
{ key: "4", type: "starship", value: "CR90 corvette" },
{ key: "5", type: "starship", value: "Star Destroyer" },
{ key: "6", type: "person", value: "Luke Skywalker" },
{ key: "7", type: "person", value: "Darth Vader" },
{ key: "8", type: "person", value: "Leia Organa" }
];
let available = [];
const Setup = () => {
const [state, setState] = useState("");
useEffect(() => {
available = array.filter((a) => a.value.toLowerCase().startsWith(state));
}, [state]);
const show = state ? available : array;
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{show.map((a) => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = (props) => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
and here is the working example : here
You can simply just pull out useEffect.
import React, { useState } from 'react';
const array = [
{ key: '1', type: 'planet', value: 'Tatooine' },
{ key: '2', type: 'planet', value: 'Alderaan' },
{ key: '3', type: 'starship', value: 'Death Star' },
{ key: '4', type: 'starship', value: 'CR90 corvette' },
{ key: '5', type: 'starship', value: 'Star Destroyer' },
{ key: '6', type: 'person', value: 'Luke Skywalker' },
{ key: '7', type: 'person', value: 'Darth Vader' },
{ key: '8', type: 'person', value: 'Leia Organa' },
];
let available = [];
const Setup = () => {
const [state, setState] = useState('');
available = array.filter(a => a.value.startsWith(state));
const show = state ? available : array;
return (
<>
<input
value={state}
onChange={e => setState(e.target.value)}
type='text'
className='form'
/>
{show.map(a => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = props => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
This must solve it
import React, { useEffect, useState } from "react";
const array = [
{ key: "1", type: "planet", value: "Tatooine" },
{ key: "2", type: "planet", value: "Alderaan" },
{ key: "3", type: "starship", value: "Death Star" },
{ key: "4", type: "starship", value: "CR90 corvette" },
{ key: "5", type: "starship", value: "Star Destroyer" },
{ key: "6", type: "person", value: "Luke Skywalker" },
{ key: "7", type: "person", value: "Darth Vader" },
{ key: "8", type: "person", value: "Leia Organa" }
];
const Setup = () => {
const [state, setState] = useState("");
const [available, setAvailable] = useState(array);
useEffect(() => {
setAvailable(array.filter((a) => a.value.startsWith(state)));
}, [state]);
return (
<>
<input
value={state}
onChange={(e) => setState(e.target.value)}
type="text"
className="form"
/>
{available.map((a) => {
return (
<Data
id={a.key}
key={parseInt(a.key)}
value={a.value}
type={a.type}
/>
);
})}
</>
);
};
const Data = (props) => {
return (
<>
<div>
<p>{props.value}</p>
</div>
</>
);
};
export default Setup;
Related
How can i render dynamic nested data in ReactJS? This array sample contains nested childs, each item have the same structure. There is a way to render this data recursively?
function App () {
const [data, setData] = useState([
{
id: '1',
name: 'demo1',
programParent: '',
childs: [
{
id: '2',
name: 'dem2',
programParent: '1',
childs: [
{
id: '4',
name: 'demo4',
programParent: '2',
childs: [
{
id: '5',
name: 'demo5',
programParent: '4'
}
]
}
]
},
{
id: '3',
name: 'demo3',
programParent: '1'
}
]
},
{
id: '6',
name: 'demo6',
programParent: ''
}
])
return (
<>
<div>
{
data.length &&
data.map(item => (
<div key={item.id}>
<h3>{item.name}</h3>
{
item.childs?.length && (
item.childs.map(child => (
<div key={child.id}>
<h4>-{child.name}</h4>
{
child.childs?.length && (
child.childs.map(childChild => (
<div key={childChild.id}>
<h5>--{childChild.name}</h5>
</div>
))
)
}
</div>
))
)
}
</div>
))
}
</div>
</>
)
}
export default App
You will need to render them recursively. Here is something to give you an idea, you can further customize the rendering.
import React from 'react';
import './style.css';
let Tree = ({ data }) => {
return (
<div>
{data.map((x) => {
return (
<div key={x.id}>
{x.name}
{!!x.childs?.length && (
<div style={{ marginLeft: 10 }}>
<Tree data={x.childs} />
</div>
)}
</div>
);
})}
</div>
);
};
export default function App() {
const [data, setData] = React.useState([
{
id: '1',
name: 'demo1',
programParent: '',
childs: [
{
id: '2',
name: 'dem2',
programParent: '1',
childs: [
{
id: '4',
name: 'demo4',
programParent: '2',
childs: [
{
id: '5',
name: 'demo5',
programParent: '4',
},
],
},
],
},
{
id: '3',
name: 'demo3',
programParent: '1',
},
],
},
{
id: '6',
name: 'demo6',
programParent: '',
},
]);
return (
<div>
<Tree data={data} />
</div>
);
}
Yes, with a recursive component:
const data = [
{
id: "1",
name: "demo1",
programParent: "",
childs: [
{
id: "2",
name: "dem2",
programParent: "1",
childs: [...]
},
...
]
},
...
];
export default function App() {
return <Node childs={data} name="root" />;
}
function Node({ childs, name }) {
return (
<div className="node">
<h2>{name}</h2>
{childs && childs.map((x) => <Node key={x.id} {...x} />)}
</div>
);
}
I would use a custom component for that demo
const Component = ({ item, level }) => {
const Heading = level <= 6 ? `h${level}` : "h6";
return (
<div>
<Heading>{item.name}</Heading>
{item.childs?.map((child) => (
<Component item={child} level={level + 1} />
))}
</div>
);
};
Usage
{data.length && data.map((item) => <Component item={item} level={1} />)}
Hi I am developing a Table components where I need to populate the data in table body dynamically. I am maintaining the bodyData in arrayOf:[{}]. Cells will be created dynamically based on the values in the mock data. I need to pass four different data in body from mockdata. Now all are getting passed as children. Now I need to display one of the data in table cell in badge format. For this I am trying to pass multiple children so that I can render one of the children in badge format. But When I am passing more than one children component is rendering last children value only. Could any one help me how to pass (Brand value in the table in form of badge). Thanks in advance. I have wrote down the working code and mockdata.
import mockData from './mock-data/';
const createCell = cell => ({ key: cell.key, children: cell.children});
//tried to pass like cell => ({ key: cell.key, children: cell.customerName,
//children:cell.customerAddr})
const createCellsForRow = cells => cells.map(cell => createCell(cell));
const StTable = () => {
const [selectedKey, setSelectedKey] = useState([]);
const handleRowToggle = (event, metaData) => {
event.preventDefault();
if (selectedKey !== metaData.key) {
setSelectedKey(metaData.key);
}
};
const createRow = rowData => (
{
key: rowData.key,
cells: createCellsForRow(rowData.cells),
toggleAction: {
metaData: { key: rowData.key },
onToggle: handleRowToggle,
isToggled: selectedKey === rowData.key,
toggleLabel: rowData.toggleText,
},
}
);
const createRows = data => data.map(childItem => createRow(childItem));
return (
<Table
summaryId="example-single-select"
summary="This table shows an implementation of single row selection."
numberOfColumns={4}
cellPaddingStyle="standard"
rowStyle="toggle"
dividerStyle="horizontal"
headerData={{
selectAllColumn: {
checkLabel: 'Single Selection',
},
cells: [
{ key: 'cell-0', id: 'toggle-0', children: 'Name' },
{ key: 'cell-1', id: 'toggle-1', children: 'Address' },
{ key: 'cell-2', id: 'toggle-2', children: 'Phone Number' },
{ key: 'cell-3', id: 'toggle-3', children: 'Brand' },//I need to pass this is as
//badge format.
],
}}
bodyData={[
{
rows: createRows(mockData),
},
]}
/>
);
};
export default StTable;
//mockData Sample
[
{
"key":"row-0",
toggleText:"txt",
"cells":[
{ key: 'cell-0', id: 'toggle-0', children: 'ABC' },
{ key: 'cell-1', id: 'toggle-1', children: 'ABC123' },
{ key: 'cell-2', id: 'toggle-2', children: 'P1234567890' },
{ key: 'cell-3', id: 'toggle-3', children: ['A', 'B'] },
]
]
//I am trying to change the structure because (I need to display the brand in badge format)
[
{
"key":"row-0",
toggleText:"txt",
"cells":[
{ key: 'cell-0', id: 'toggle-0', customerName: 'ABC' },
{ key: 'cell-1', id: 'toggle-1', customerAddr: 'ABC123' },
{ key: 'cell-2', id: 'toggle-2', customerPhNo: 'P1234567890' },
{ key: 'cell-3', id: 'toggle-3', customerBrand: ['A', 'B'] },
]
]
//Table Component
const createCell = cell => ({ key: cell.key, children: cell.title });
const createCellsForRow = cells => cells.map(cell => createCell(cell));
const Table = () => {
const [selectedKey, setSelectedKey] = useState([]);
const handleRowToggle = (event, metaData) => {
event.preventDefault();
if (selectedKey !== metaData.key) {
setSelectedKey(metaData.key);
}
};
const createRow = rowData => (
{
key: rowData.key,
cells: createCellsForRow(rowData.cells),
toggleAction: {
metaData: { key: rowData.key },
onToggle: handleRowToggle,
isToggled: selectedKey === rowData.key,
toggleLabel: rowData.toggleText,
},
}
);
const createRows = data => data.map(childItem => createRow(childItem));
return (
<Table
numberOfColumns={4}
cellPaddingStyle="standard"
rowStyle="toggle"
dividerStyle="horizontal"
headerData={{
selectAllColumn: {
checkLabel: 'Single Selection',
},
cells: [
{ key: 'cell-0', id: 'toggle-0', children: 'Name' },
{ key: 'cell-1', id: 'toggle-1', children: 'Address' },
{ key: 'cell-2', id: 'toggle-2', children: 'Phone Number' },
{ key: 'cell-3', id: 'toggle-3', children: 'Email Id' },
],
}}
bodyData={[
{
rows: createRows(mockData),
},
]}
/>
);
};
export default Table;
index.tsx
data = {
room: [
{
id: 1,
name: 'room1'
},
{
id: 2,
name: 'room2'
},
{
id: 3,
name: 'room3'
}
],
student: [
{
id: 1,
room: 'room1',
name: 'josh'
},
{
id: 2,
room: 'room1',
name: 'jake'
}
]
}
const _ROOM = data['room'];
const _STUDENT = data['student'];
const form = {
config: [
{
label: "Room",
name: "room",
type: "select",
rule: yup.string().required(),
renderer: (data: any) => {
const { control, register, errors } = useFormContext();
return (
<SelectPicker
placeholder="Room"
data={
_ROOM && _ROOM.length > 0 ?
_ROOM.map(x => ({ label: x.name, value: x.id })) : []
}
style={{ width: '100%' }}
onChange={(val) => {
control.setValue('room', val);
}}
value={control.getValues()['room']}
/>
);
}
},
{
label: "Student",
name: "student",
type: "select",
rule: yup.string().required(),
renderer: (data: any) => {
const { control, register, errors } = useFormContext();
return (
<SelectPicker
placeholder="Student"
data={
_STUDENT && _STUDENT.length > 0 ?
_STUDENT.map(x => ({ label: x.name, value: x.id })) : []
}
style={{ width: '100%' }}
onChange={(val) => control.setValue('student', val)}
value={control.getValues()['student']}
/>
);
}
}]}
How to filter the student based on the room. for example I select the room1 then on the student it will filter which it has value room1. I try to filter inside the onchange in room but it doesn't work also not filtering or display the console log. also I used the state then set inside the onChange but it doesn't work also.
Take a look at this: https://react-hook-form.com/advanced-usage/#ConditionalControlledComponent
Basically, you can watch for changes in room and filter out the options in the student field.
const {room} = watch();
And in the SelectPicker, modify the data prop to:
data={
_STUDENT && _STUDENT.length > 0 ?
_STUDENT.filter(s => s.room === room).map(x => ({ label: x.name, value: x.id })) : []
}
Hy, let me explain my problem, i have a state of tag called tag_data :
const [tagData, setTagData] = useState([
{ key: '1', label: 'Music', active: 0 },
{ key: '2', label: 'Sport', active: 0 },
{ key: '3', label: 'Dance', active: 0 },
{ key: '4', label: 'Cook', active: 0},
{ key: '5', label: 'Video Games', active: 0},
{ key: '6', label: 'Travel', active: 0 },
{ key: '7', label: 'Picture', active: 0 },
{ key: '8', label: 'Animals', active: 0 },
{ key: '9', label: 'Coding', active: 0},
{ key: '10', label: 'Party', active: 0},
])
I do a api call for get ACTIVE tag from my user :
useEffect(() => {
const fetchData = async () => {
setLoad(true)
try {
const result = await axios.post('/user/activetag')
console.log(result.data.active_tag)
setTagData({
// update
})
} catch (error) {
console.log(error)
}
setLoad(false)
}
fetchData()
}, [])
Then the result store the active tags like this :
active_tag: Array(5)
0: {tag_id: 1, label: "Music"}
1: {tag_id: 2, label: "Sport"}
2: {tag_id: 3, label: "Dance"}
3: {tag_id: 4, label: "Cook"}
4: {tag_id: 5, label: "Video Games"}
I would like to update the tagData state and put active to 1 where the tag_id is equal to the key of tagData state, any idea ?
Full code :
import React, {useState, useEffect} from "react";
import { makeStyles } from '#material-ui/core/styles';
import Chip from '#material-ui/core/Chip';
import Paper from '#material-ui/core/Paper';
import DoneIcon from '#material-ui/icons/Done';
import axios from 'axios'
import Loading from '../../../../Loading/Loading'
const useStyles = makeStyles((theme) => ({
// style
})
export default function TagUser(){
const classes = useStyles();
const [load, setLoad] = useState(false)
const [tagData, setTagData] = useState([
{ key: '1', label: 'Music', active: 0 },
{ key: '2', label: 'Sport', active: 0 },
{ key: '3', label: 'Dance', active: 0 },
{ key: '4', label: 'Cook', active: 0},
{ key: '5', label: 'Video Games', active: 0},
{ key: '6', label: 'Travel', active: 0 },
{ key: '7', label: 'Picture', active: 0 },
{ key: '8', label: 'Animals', active: 0 },
{ key: '9', label: 'Coding', active: 0},
{ key: '10', label: 'Party', active: 0},
])
useEffect(() => {
const fetchData = async () => {
setLoad(true)
try {
const result = await axios.post('/user/activetag')
console.log(result.data)
setTagData({
// update
})
} catch (error) {
console.log(error)
}
setLoad(false)
}
fetchData()
}, [])
const handleDelete = (key) => {
//delete
}
const handleSubmit = (key) => {
//submit
}
if(load){
return <Loading/>
} else {
return(
<Paper variant="outlined" square component="span" className={classes.root}>
{
tagData.map((data) => {
if (data.active === 0) {
return (
<li key={data.key}>
<Chip
variant="outlined"
color="secondary"
label={data.label}
className={classes.chip}
onDelete={() => handleSubmit(data.key)}
deleteIcon={<DoneIcon />}
/>
</li>
)
} else {
return (
<li key={data.key}>
<Chip
color="secondary"
label={data.label}
className={classes.chip}
onDelete={() => handleDelete(data.key)}
/>
</li>
)
}
})
}
</Paper>
)
}
}
Disclosure: I am the author of the suspense-service library used in this answer.
If you're open to using a 3rd-party library, it can significantly simplify your data-fetching logic. You won't need a load state, or a useEffect(), the component will only render when the list is ready:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Chip from '#material-ui/core/Chip';
import Paper from '#material-ui/core/Paper';
import DoneIcon from '#material-ui/icons/Done';
import axios from 'axios';
import { createService, useService } from 'suspense-service';
import Loading from '../../../../Loading/Loading';
const defaultTags = [
{ key: '1', label: 'Music', active: 0 },
{ key: '2', label: 'Sport', active: 0 },
{ key: '3', label: 'Dance', active: 0 },
{ key: '4', label: 'Cook', active: 0},
{ key: '5', label: 'Video Games', active: 0},
{ key: '6', label: 'Travel', active: 0 },
{ key: '7', label: 'Picture', active: 0 },
{ key: '8', label: 'Animals', active: 0 },
{ key: '9', label: 'Coding', active: 0},
{ key: '10', label: 'Party', active: 0},
];
const UserActiveTags = createService(async (allTags) => {
try {
const result = await axios.post('/user/activetag');
console.log(result.data.active_tag);
const activeTags = result.data.active_tag.map((tag) => tag.tag_id);
const activeTagsSet = new Set(activeTags);
return allTags.map((tag) => ({
...tag,
active: activeTagsSet.has(tag.key) ? 1 : 0
}));
} catch (error) {
console.log(error);
return allTags;
}
});
export default function TagUser() {
return (
<UserActiveTags.Provider request={defaultTags} fallback={<Loading />}>
<TagList />
</UserActiveTags.Provider>
);
}
const useStyles = makeStyles((theme) => ({
// style
}));
function TagList() {
const { root, chip } = useStyles();
const tagData = useService(UserActiveTags);
const handleDelete = (key) => {
//delete
};
const handleSubmit = (key) => {
//submit
};
const tagList = tagData.map(({ active, key, label }) => {
const props = active === 0
? { variant: 'outlined', onDelete: () => handleSubmit(key), deleteIcon: <DoneIcon /> }
: { variant: 'default', onDelete: () => handleDelete(key) };
return (
<li key={key}>
<Chip
color="secondary"
label={label}
className={chip}
{...props}
/>
</li>
);
});
return (
<Paper variant="outlined" square={true} component="span" className={root}>
{tagList}
</Paper>
);
}
If you need tagData to be stateful, then
const tagData = useService(UserActiveTags);
needs to be updated to this:
const initialTagData = useService(UserActiveTags);
const [tagData, setTagData] = useState(initialTagData);
useEffect(() => {
setTagData(initialTagData);
}, [initialTagData]);
I think you could something like this,
In your useEffect(),
const result = await axios.post('/user/activetag');
const filteredTags = tagData.map((e) => {
const checkActive = result.data.some(i => i.tag_id == e.key);
if(checkActive){
const temp = {...e};
temp.active = 1;
return temp;
}
return e;
});
setTagData(filteredTags);
Hope that works!
I am trying to apply this example to my own code, but it seems that "ref" properties are obsolete in this form. Can anyone help me with this code? Right now i am getting "Cannot read property 'focus' of undefined", when clicking on filter
const data = [{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
}, {
key: '2',
name: 'Joe Black',
age: 42,
address: 'London No. 1 Lake Park',
}, {
key: '3',
name: 'Jim Green',
age: 32,
address: 'Sidney No. 1 Lake Park',
}, {
key: '4',
name: 'Jim Red',
age: 32,
address: 'London No. 2 Lake Park',
}];
class App extends React.Component {
state = {
searchText: '',
};
handleSearch = (selectedKeys, confirm) => () => {
confirm();
this.setState({ searchText: selectedKeys[0] });
}
handleReset = clearFilters => () => {
clearFilters();
this.setState({ searchText: '' });
}
render() {
const columns = [{
title: 'Name',
dataIndex: 'name',
key: 'name',
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
<div className="custom-filter-dropdown">
<Input
ref={ele => this.searchInput = ele}
placeholder="Search name"
value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={this.handleSearch(selectedKeys, confirm)}
/>
<Button type="primary" onClick={this.handleSearch(selectedKeys, confirm)}>Search</Button>
<Button onClick={this.handleReset(clearFilters)}>Reset</Button>
</div>
),
filterIcon: filtered => <Icon type="smile-o" style={{ color: filtered ? '#108ee9' : '#aaa' }} />,
onFilter: (value, record) => record.name.toLowerCase().includes(value.toLowerCase()),
onFilterDropdownVisibleChange: (visible) => {
if (visible) {
setTimeout(() => {
this.searchInput.focus();
});
}
},
render: (text) => {
const { searchText } = this.state;
return searchText ? (
<span>
{text.split(new RegExp(`(?<=${searchText})|(?=${searchText})`, 'i')).map((fragment, i) => (
fragment.toLowerCase() === searchText.toLowerCase()
? <span key={i} className="highlight">{fragment}</span> : fragment // eslint-disable-line
))}
</span>
) : text;
},
}, {
title: 'Age',
dataIndex: 'age',
key: 'age',
}, {
title: 'Address',
dataIndex: 'address',
key: 'address',
filters: [{
text: 'London',
value: 'London',
}, {
text: 'New York',
value: 'New York',
}],
onFilter: (value, record) => record.address.indexOf(value) === 0,
}];
return <Table columns={columns} dataSource={data} />;
}
}
ReactDOM.render(<App />, mountNode);
code that I am trying to execute
https://hastebin.com/yipusowala.coffeescript
{
title: 'Rider',
key: 'rider',
width: '25%',
dataIndex: 'rider.name',
filterDropdown: ({setSelectedKeys, selectedKeys, confirm, clearFilters}) => (
<div className="custom-filter-dropdown">
<Input
ref={(input) => { this.searchInput= input; }}
placeholder="Search name"
value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={this.handleSearch(selectedKeys, confirm)}
/>
<Button type="primary" onClick={this.handleSearch(selectedKeys, confirm)}>Search</Button>
<Button onClick={this.handleReset(clearFilters)}>Reset</Button>
</div>
),
onFilter: (value, record) => record.rider.name.toLowerCase().includes(value.toLowerCase()),
onFilterDropdownVisibleChange: (visible) => {
if (visible) {
setTimeout(() => {
this.searchInput.focus();
});
}
},
render: (text) => {
const {userFilterText} = this.state.userFilterText;
return userFilterText ? (
<span>
{text.split(new RegExp(`(?<=${userFilterText})|(?=${userFilterText})`, 'i')).map((fragment, i) => (
fragment.toLowerCase() === userFilterText.toLowerCase()
? <span key={i} className="highlight">{fragment}</span> : fragment // eslint-disable-line
))}
</span>) : text;
}
},
Your code seems just fine
(apart from this object destructuring:
const {userFilterText} = this.state.userFilterText;
which I'm guessing is a typo)
I created this sandbox based on the example you described and the ref for the <Input /> component as well as the .focus() trigger - seem to be working fine. (check out the console and you can see the Input ref being logged)
Hope this helps :)