Here is my entire code at Home.js file
export default function Home({navigation}) {
const [reviews, setReviews] = useState([
{ title: 'Alfa Romeo 147 1.9JTD', rating: 2020, body: 340000, sg: ['ABS ', 'CD ', 'ESP '], key: '1' },
{ title: 'Gotta Catch Them All (again)', body: 'lorem ipsum', key: '2' },
{ title: 'Not So "Final" Fantasy', body:'lorem ipsum', key: '3' },
{ title: 'Alfaromeo', rating: 3200, body: 'blablabla', first:'loremlo', key: '4' },
{ title: 'Gotta Catch Them All (again)', rating: 4, body: 'lorem ipsum', key: '5' },
{ title: 'Not So "Final" Fantasy', rating: 3, body: 'lorem ipsum', key: '6' },
{ title: 'Alfaromeo', rating: 3200, body: 'sadaa', key: '7' },
{ title: 'Gotta Catch Them All (again)', rating: 4, body: 'lorem ipsum', key: '8' },
]);
return (
<View style={styles.container}>
<FlatList data={reviews} renderItem={({ item }) => (
<TouchableOpacity onPress={() => navigation.navigate('ReviewDetails', item)}>
<View style={styles.content}>
<Image
style={styles.image}
source={{
uri: 'https://www.autoplac-cg.me/storage/1871/conversions/5f9eb91821de1_20FB3486-4A0A-4B4A-B13C-CAE912950E22-thumb.jpg',
}}
/>
<Text style={styles.headertext}>{item.title }</Text>
<Text style={styles.infotext}>{item.rating}god. | {item.body}km <Text style={styles.collapse}>+</Text></Text>
</View>
</TouchableOpacity>
)} />
</View>
);
}
So I want to put first on FlatList that review who has in array 'first', so in code its fourth. How I can do that?
I want to this be first on FlatList
{ title: 'Alfaromeo', rating: 3200, body: 'blablabla', first:'loremlo', key: '4' }
I believe that the best way to do that is to sort the data as needed and then render it with FlatList.
The sort logic may be the way you need, which means that you are free to "order by 'anything'" if you wish.
According to the data set and information you provided, the business rule, as I understood, is to show the items with fisrt flag at first place. So, the sorting could be like this:
export default function Home({navigation}) {
const [reviews, setReviews] = useState([
{ title: 'Alfa Romeo 147 1.9JTD', rating: 2020, body: 340000, sg: ['ABS ', 'CD ', 'ESP '], key: '1' },
{ title: 'Gotta Catch Them All (again)', body: 'lorem ipsum', key: '2' },
{ title: 'Not So "Final" Fantasy', body:'lorem ipsum', key: '3' },
{ title: 'Alfaromeo', rating: 3200, body: 'blablabla', first:'loremlo', key: '4' },
{ title: 'Gotta Catch Them All (again)', rating: 4, body: 'lorem ipsum', key: '5' },
{ title: 'Not So "Final" Fantasy', rating: 3, body: 'lorem ipsum', key: '6' },
{ title: 'Alfaromeo', rating: 3200, body: 'sadaa', key: '7' },
{ title: 'Gotta Catch Them All (again)', rating: 4, body: 'lorem ipsum', key: '8' },
]);
function renderItem(item) {
return (
<TouchableOpacity onPress={() => navigation.navigate('ReviewDetails', item)}>
<View style={styles.content}>
<Image
style={styles.image}
source={{
uri: 'https://www.autoplac-cg.me/storage/1871/conversions/5f9eb91821de1_20FB3486-4A0A-4B4A-B13C-CAE912950E22-thumb.jpg',
}}
/>
<Text style={styles.headertext}>{item.title}</Text>
<Text style={styles.infotext}>{item.rating}god. | {item.body}km <Text style={styles.collapse}>+</Text></Text>
</View>
</TouchableOpacity>
);
}
function sortData() {
let sortedArray = [];
// If the item contains "first" property, it will be placed at the beginning of the sortedArray, else it will be at the end of it
reviews.forEach(review => (
review.first
? sortedArray = [review, ...sortedArray]
: sortedArray.push(review)
));
return sortedArray;
}
return (
<View style={styles.container}>
<FlatList
data={sortData()}
renderItem={({ item }) => renderItem(item)}
/>
</View>
);
}
I moved the code to render an item to a separated function just for convenience
Use array.sort with providing compare function
See: https://www.w3schools.com/js/js_array_sort.asp
You can use
reviews.sort((a, b) => a.rating - b.rating)
This will sort your reviews array.
You can do is
var reviews1 = reviews.filter(function (el) {
return el["first"];
});
var reviews2 = reviews.filter(function (el) {
return el["first"] === undefined;
});
const reviewsFinalArray = reviews1.concat(reviews2); // Your result
Related
I'm trying to create a SectionList from data received from an API. This API has the following structure for the ingredients that I want to display:
const ingredients = {
malt: [
{
name: 'Maris Otter Extra Pale',
amount: {
value: 3.3,
unit: 'kilograms',
},
},
{
name: 'Caramalt',
amount: {
value: 0.2,
unit: 'kilograms',
},
},
{
name: 'Munich',
amount: {
value: 0.4,
unit: 'kilograms',
},
},
],
hops: [
{
name: 'Fuggles',
amount: {
value: 25,
unit: 'grams',
},
add: 'start',
attribute: 'bitter',
},
{
name: 'First Gold',
amount: {
value: 25,
unit: 'grams',
},
add: 'start',
attribute: 'bitter',
},
{
name: 'Fuggles',
amount: {
value: 37.5,
unit: 'grams',
},
add: 'middle',
attribute: 'flavour',
},
{
name: 'First Gold',
amount: {
value: 37.5,
unit: 'grams',
},
add: 'middle',
attribute: 'flavour',
},
{
name: 'Cascade',
amount: {
value: 37.5,
unit: 'grams',
},
add: 'end',
attribute: 'flavour',
},
],
yeast: 'Wyeast 1056 - American Aleā¢',
};
The desired result is the following using SectionList (with malt and hops as section headers):
Visual example of result
I've already tried to use functions like Object.values(), with no result at all. The code simply looks like the following, receiving the beer from the previous view(with a beer list):
const Detail = ({ route }) => {
const beer = route.params.beer;
const ingredientsFormatted = Object.values(beer.ingredients);
return(
<SectionList
sections={ingredientsFormatted}
renderItem={({ item }) => {
<Text>{item.name}</Text>; //Here there has to be the name of the different ingredients
}}
renderSectionHeader={({ section }) => <Text>{section}</Text>} //Here there has to be malt, hops or yeast
keyExtractor={(item) => item.name}
></SectionList>
)}
There are 2 problems in your ingredients data.
Format in value for yeast is not the same as the others.
Your data inserted into SectionList is not the format recommended by React-Native Offical docs.
To fix this, you can modify your API return / map the data after retrieved from server.
const Detail = ({ route }) => {
const beer = route.params.beer;
let sectionListTemplate = [];
for (let [key, value] of Object.entries(beer.ingredients)) {
//console.log(`${key}: ${JSON.stringify(value)}`);
if(!Array.isArray(value)){
//Handle case for 'yeast' which its data is not an array
sectionListTemplate.push({
title: key,
data: [{
name: value
}]
})
}
else{
//Map value for general cases
sectionListTemplate.push({
title: key,
data: value
})
}
}
return(
<SectionList
sections={sectionListTemplate}
renderSectionHeader={({ section }) => {
return(
//Here there has to be malt, hops or yeast
<Text style={{fontWeight: 'bold'}}>
{section.title}
</Text>
)
}}
renderItem={({ item }) => {
return(
//Here there has to be the name of the different ingredients
<Text>
{item.name}
</Text>
)
}}
keyExtractor={(item) => item.name}
>
</SectionList>
)
)}
I am having a little difficulty with my data. I was able to get all mapped data currently but without me clicking the categories, the data won't be displayed.
Here's an example:
const categoriesData = [
{
name: 'All',
label: 'All',
total: '18',
className: 'activeCategory'
},
{
name: 'Business Services',
label: 'Business_Services',
total: '18'
},
{
name: 'Design Services',
label: 'Design_Services',
total: '18'
},
{
name: 'Education Services',
label: 'Education_Services',
total: '18'
},
{
name: 'Finance Services',
label: 'Finance_Services',
total: '18'
},
{
name: 'IT Services',
label: 'IT_Services',
total: '18'
},
{
name: 'Legal Services',
label: 'Legal_Services',
total: '18'
},
{
name: 'Manufacturing',
label: 'Manufacturing',
total: '18'
},
{
name: 'Marketing',
label: 'Marketing',
total: '18'
}
];
const postsData = {
All: [
{ id: 1, name: 'Post 3' },
{ id: 2, name: 'Post 2' }
],
Business_Services: [
{ id: 1, name: 'Post 3' },
{ id: 2, name: 'Post 2' }
],
Design_Services: [
{ id: 1, name: 'Post 5' },
{ id: 2, name: 'Post 2' }
],
Education_Services: [
{ id: 1, name: 'Post 1' },
{ id: 2, name: 'Post 2' }
],
Finance_Services: [
{ id: 1, name: 'Post 1' },
{ id: 2, name: 'Post 2' }
],
IT_Services: [
{ id: 1, name: 'Post 1' },
{ id: 2, name: 'Post 2' }
],
Legal_Services: [
{ id: 1, name: 'Post 1' },
{ id: 2, name: 'Post 2' }
],
Manufacturing: [
],
Marketing: [
{ id: 1, name: 'Post 1' },
{ id: 2, name: 'Post 27675' }
]
};
function fakePostsApi(catName) {
return new Promise((resolve) =>
setTimeout(() => {
resolve(postsData[catName]);
}, 1000)
);
}
function Main() {
const [categories, setCategories] = React.useState(categoriesData);
const [catName, setCatName] = React.useState();
const [posts, setPosts] = React.useState([]);
React.useEffect(() => {
if (catName) {
fakePostsApi(catName)
.then(setPosts);
}
}, [catName]);
return (
<div>
{categories.length > 0 ? (
categories.map((category, i) => {
return (
<button key={i} onClick={() => setCatName(category.label)}>
{category.name}
</button>
);
})
) : (
<p>Loading...</p>
)}
<div>
{posts.length === 0 ? (
<p>No posts...</p>
) : (
posts.map((post) => <div key={post.id}>{post.name}</div>)
)}
</div>
</div>
);
}
ReactDOM.render(
<Main />,
root
)
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>
My main problem is: I want the values of all to be displayed first(just like active status) when page loads without being clicking the All button.
Set the default value of catName to be the label of the 0 item of the categories:
const [catName, setCatName] = React.useState(categories[0] && categories[0].label);
Or optional chaining (?.) if supported:
const [catName, setCatName] = React.useState(categories[0]?.label);
const categoriesData = [{"name":"All","label":"All","total":"18","className":"activeCategory"},{"name":"Business Services","label":"Business_Services","total":"18"},{"name":"Design Services","label":"Design_Services","total":"18"},{"name":"Education Services","label":"Education_Services","total":"18"},{"name":"Finance Services","label":"Finance_Services","total":"18"},{"name":"IT Services","label":"IT_Services","total":"18"},{"name":"Legal Services","label":"Legal_Services","total":"18"},{"name":"Manufacturing","label":"Manufacturing","total":"18"},{"name":"Marketing","label":"Marketing","total":"18"}];
const postsData = {"All":[{"id":1,"name":"Post 3"},{"id":2,"name":"Post 2"}],"Business_Services":[{"id":1,"name":"Post 3"},{"id":2,"name":"Post 2"}],"Design_Services":[{"id":1,"name":"Post 5"},{"id":2,"name":"Post 2"}],"Education_Services":[{"id":1,"name":"Post 1"},{"id":2,"name":"Post 2"}],"Finance_Services":[{"id":1,"name":"Post 1"},{"id":2,"name":"Post 2"}],"IT_Services":[{"id":1,"name":"Post 1"},{"id":2,"name":"Post 2"}],"Legal_Services":[{"id":1,"name":"Post 1"},{"id":2,"name":"Post 2"}],"Manufacturing":[],"Marketing":[{"id":1,"name":"Post 1"},{"id":2,"name":"Post 27675"}]};
function Main() {
const [categories, setCategories] = React.useState(categoriesData);
const [catName, setCatName] = React.useState(categories[0] && categories[0].label);
const [posts, setPosts] = React.useState([]);
React.useEffect(() => {
if (catName) {
fakePostsApi(catName)
.then(setPosts);
}
}, [catName]);
return (
<div>
{categories.length > 0 ? (
categories.map((category, i) => {
return (
<button key={i} onClick={() => setCatName(category.label)}>
{category.name}
</button>
);
})
) : (
<p>Loading...</p>
)}
<div>
{posts.length === 0 ? (
<p>No posts...</p>
) : (
posts.map((post) => <div key={post.id}>{post.name}</div>)
)}
</div>
</div>
);
}
function fakePostsApi(catName) {
return new Promise((resolve) =>
setTimeout(() => {
resolve(postsData[catName]);
}, 1000)
);
}
ReactDOM.render(
<Main />,
root
)
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>
I have the following Data which when downloaded can be viewed in an xls/csv format. I am using react-csv npm package which is displaying the name and description in same columns as opposed to different columns.
I need some help in figuring out how to display data where Name, Description, and Roles are displayed in different columns as shown below.
Data:-
const csvData = [
{
name: 'Data science training',
description:
'Data Science certification training',
suggestedRoles: [
{ id: 16, category: 'DEVELOPER', name: 'Data Engineer' },
{ id: 17, category: 'DEVELOPER', name: 'Data Scientist' }]
},{
name: 'AWS',
description:
'AWS certification training',
suggestedRoles: [
{ id: 16, category: 'DEVELOPER', name: 'Cloud Engineer' },
{ id: 17, category: 'DEVELOPER', name: 'Network Engineer' }]
}],
Expected Output:-
Name Description RoleName
Data Science Training Data Science Certification Training Data Engineer
Data Scientist
AWS Training AWS Certification Training Cloud Engineer
Network Engineer
Current Output:-
Name Description RoleName
Data Science Training,AWS Training Data Science Certification Training, AWS Certification Training Data Engineer,Data Scientist,Cloud Engineer,Network Engineer
Code:-
export const ReactCsv = () => {
const createCsvFileName = ()=> `data_${moment().format()}.csv`;
const headers = [
{ label: 'Name', key: 'name' },
{ label: 'Description', key: 'description' },
{ label: 'SuggestedRoles', key: 'suggestedRoles' }
];
const data = [
{
name: csvData.map((_)=>_.name),
description: csvData.map((_)=>_.description),
suggestedRoles: csvData.map((_)=>_.suggestedRoles.map((role)=>role.name)),
}
];
return (
<CSVLink
data={data}
headers={headers}
filename={createCsvFileName()}
target="_blank"
style={{ textDecoration: 'none', outline: 'none', height: '5vh' }}
>
<Button variant="contained" color="secondary" style={{ height: '100%' }}>
Download CSV
</Button>
</CSVLink>
);
};
The data variable must be an array of objects, not an array of a single object where each property is an array of values.
const csvData = [{
name: 'Data science training',
description: 'Data Science certification training',
suggestedRoles: [{
id: 16,
category: 'DEVELOPER',
name: 'Data Engineer'
},
{
id: 17,
category: 'DEVELOPER',
name: 'Data Scientist'
}
]
}, {
name: 'AWS',
description: 'AWS certification training',
suggestedRoles: [{
id: 16,
category: 'DEVELOPER',
name: 'Cloud Engineer'
},
{
id: 17,
category: 'DEVELOPER',
name: 'Network Engineer'
}
]
}];
const data = csvData.map(item => ({
name: item.name,
description: item.description,
suggestedRoles: item.suggestedRoles.map(role => role.name),
}))
console.log(data);
Your ReactCsv's data generating code should be changed into like this one.
export const ReactCsv = () => {
const createCsvFileName = ()=> `data_${moment().format()}.csv`;
const headers = [
{ label: 'Name', key: 'name' },
{ label: 'Description', key: 'description' },
{ label: 'SuggestedRoles', key: 'suggestedRoles' }
];
let data = []
csvData.forEach(item => {
data.push({
name: item.name,
description: item.description,
suggestedRoles: item.suggestedRoles[0].name
});
for (let i = 1; i < item.suggestedRoles.length; i++) {
const role = item.suggestedRoles[i];
data.push({
name: '',
description: '',
suggestedRoles: role.name
});
}
});
return (
<CSVLink
data={data}
headers={headers}
filename={createCsvFileName()}
target="_blank"
style={{ textDecoration: 'none', outline: 'none', height: '5vh' }}
>
<Button variant="contained" color="secondary" style={{ height: '100%' }}>
Download CSV
</Button>
</CSVLink>
);
};
The data property should be one single object. So, what you can do is create a function that returns an object. That object structure you can decide based on the data and attributes you want to display.
eg:
const newBillingReport = () => {
try {
const newBillingReportData = billingExportReportData.map((data) => ({
"Type": data?.type || "Not Provided",
"Status": data?.status || "Not Provided",
"Billed": data?.billedAmount || "0",
}),[])
return newBillingReportData
} catch (error) {
console.error(error)
}
}
This will returns object with three attributes:
eg:
{
"Type": "COMPLETED",
"Status": "DONE",
"Billed": "True"
}
So like this you can create a function. Then for the header attribute map same as you returned. That should also will be a function that returns an object
eg:
const formatUserName = () => {
return [
{ label: "Type", key: "Type" },
{ label: "Status", key: "Status" },
{ label: "Billed ($)", key: "Billed" },
]
}
In here you can see how you need to add label and keys. Most likely the function return data.
So CVLink like this
headers={headers}
data={newBillingReport()}
headers should call the function const headers = formatUserName()
I have this two collection in Firestore which I would like to display in one Flatlist in React Native.
First collection looks like this: (this is created by the user)
collection_1 : [
{
id: a1b2c3,
name: 'joe'
}
{
id2: d4e5f6,
name: 'jane'
}
]
and second collection looks like this: (this is created by the friend user)
collection_2: [
{
id: z9y8x7
userId: 'a1b2c3',
seenCount: 10,
},
{
id: w7v6u5
userId: 'd4e5f6'
seenCount: 5,
},
]
and I would like to display the list with the name and the seen count next to each other with the condition of the collection_1 id is the same with the collection_2 userId:
joe (10)
jane (5)
but currently my I only have collection_1 in my flatlist:
<FlatList
data={collection_1}
keyExtractor={(item, index) => String(index)}
renderItem={({ item }) => (
<View>
<Text>
{item.name}
</Text>
</View>
)}
/>
is it possible with Flatlist? or is there a better way to this?
You should create a new array from 2 collection lists. data is what you need in the below example.
const collection1 = [
{
id: 'a1b2c3',
name: 'joe'
},
{
id: 'd4e5f6',
name: 'jane'
}
];
const collection2 = [
{
id: 'z9y8x7',
userId: 'a1b2c3',
seenCount: 10
},
{
id: 'w7v6u5',
userId: 'd4e5f6',
seenCount: 5
},
{
id: 'o1j3o2',
userId: 'd4e5f6',
seenCount: 7
}
];
const seenCounts = {};
collection2.forEach((item) => {
if (seenCounts[item.userId]) {
seenCounts[item.userId] += item.seenCount;
} else {
seenCounts[item.userId] = item.seenCount;
}
});
const data = collection1.map((item) => ({
...item,
seenCount: seenCounts[item.id]
}));
console.log(data);
You need to combine the arrays so that your object consist of both name and screen (Please run snippet).
Then u can do it like this.
<FlatList
data={final} //this is the combined array
keyExtractor={(item, index) => String(index)}
renderItem={({ item }) => (
<View>
<Text>
{item.name} ({item.seenCount})
</Text>
</View>
)}
/>
Combine Array
let collection_1 = [{
id: 'a1b2c3',
name: 'joe'
},
{
id: 'd4e5f6',
name: 'jane'
}
]
let collection_2 = [{
id: 'z9y8x7',
userId: 'a1b2c3',
seenCount: 10,
},
{
id: 'w7v6u5',
userId: 'd4e5f6',
seenCount: 5,
}
]
let final = collection_2.map(user => {
let name = collection_1.filter((users) => users.id === user.userId)[0].name
return { ...user,
name
}
})
console.log('final', final)
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 :)