React Native custom cross-platform dropdown select element - javascript

I have searched quite thoroughly with not much luck. I am having trouble implementing a simple custom dropdown select element for my application.
I am hoping for a cross-platform (iOS & Android) solution like the simple custom JS dropdown featured here https://www.w3schools.com/howto/howto_custom_select.asp
Is this something I should just be creating myself with react native views and some state? I'm still trying to get a feel of what solutions are unrealistic. Could anyone give me an example from a professional project?
I am trying to avoid using the native Picker from here since I cannot style them to match my designer's needs. https://github.com/react-native-community/react-native-picker
I tried this package but it seems to be having trouble with the latest versions and I need something reliable. https://github.com/sohobloo/react-native-modal-dropdown
I was also looking at this package as it seems to be nearly perfect for my needs but again it has not been updated in 2 years https://github.com/n4kz/react-native-material-dropdown

My recommendation would be to go with something out there, as I will generally make implementation quicker for you, although as you say there might be a trade off in styling.
I've recently been in the situation a few times where I've really had to look hard for good, maintained components for React Native, but they certainly exist.
I've been successfully using react-native-paper recently. You could consider their accordion drop down list but may not suit in styling as it follows material UI guidelines.
https://callstack.github.io/react-native-paper/

I used this in my project and it works perfectly:
https://github.com/mrlaessig/react-native-autocomplete-input
you can just use the onFocus prop to make it dropdown with a click instead of when the user firsts typing and onEndEditing prop to hide it when the user selects an option.
here's my full implementation for reference, I had to go into the code a bit to check for these props since the documentation didn't include it.
<Autocomplete
data={filterNames()}
placeholder={'Who are you here to see?'}
onChangeText={item => setTextAndShowResults(item)}
onFocus={() => setHideResults(false)}
onEndEditing={() => setHideResults(true)}
defaultValue={getDefaultValue()}
keyExtractor={(item, i) => {
return item.id;
}}
returnKeyType={'next'}
listStyle={styles.listStyle}
inputContainerStyle={styles.borderWidth0}
style={styles.autoCompleteButtonStyle}
hideResults={hideResults}
renderItem={({ item, i }) => (
<TouchableOpacity onPress={() => setTextAndHideResults(item)}>
<Text style={styles.listTextStyle}>{item.name}</Text>
</TouchableOpacity>
)}
/>

Related

How to use inlineImageLeft in an Expo React Native project

So I was going through the React Native docs on <TextInput />
I saw a property called 'inlineImageLeft' and it seemed to add an icon on the left side of the <TextInput />.
But in the docs, its specified that the icon should be stored in /android/app/src/main/res/drawable
But I am using an Expo generated project. Is it possible to use this property on Expo?
Here is the example I tried from the react-native docs but it didn't work:
<TextInput
placeholder={`Search for ${currentMode}`}
style={styles.input}
value={searchState.search}
onChangeText={handleChange}
placeholderTextColor='white'
autoCorrect={false}
inlineImageLeft='search_icon' // Does not work
/>
If you are using the managed workflow (which it sounds like you are) then it is not possible to use inlineImageLeft. Even if you were in the bare workflow, this only works for Android.
You will have to build your own component that renders an icon/image inside the text input. Something like this: How can I put an icon inside a TextInput in React Native?

resizable prop no longer working in react-big-calendar

I was building a scheduling app with react-big-calendar and I have noticed from React v17 onwards the resizable does not work because of the way react handles event changing.
this is the issue: https://github.com/jquense/react-big-calendar/issues/1785
I have seen in the comments that someone fixed this issue and made a pull request: https://github.com/jquense/react-big-calendar/pull/1857
My problem is that it is still not working, the resizable handles does not show up on the big calendar. I made sure I am using the latest version 0.33.6 and also tried to figure out where the user did the changes to events to fix the issue so that I can modify the package, but I noticed they both are completely different files, I wasn't able to find the event handlers in my node_modules/react-big-calendar so that I can make edits. So how do I fix this error? I cannot revert back to reactv16 because I must use v17 in my project.
Thanks in Advance! :)
Here's what my calendar looks like:
<DragAndDropCalendar
selectable
resizable
onEventDrop={onEventDrop}
onEventResize={resizeEvent}
localizer={localizer}
events={events}
onSelectSlot={handleSelect}
defaultView="week"
defaultDate={new Date()}
timeslots={2}
step={15}
popup
tooltipAccessor={(e) => e.title}
/>
</div>

Integrating jQuery plugin with React

I'm using jQuery nestable plugin https://dbushell.com/Nestable/ in my React App. I know that there will be problems when we use jQuery in React.
jQuery nestable solves my business needs, can't find the exact requirements in react drag/nestable components. So I have used this jQuery plugin.
The real problem is : while dragging an element by using this jQuery plugin, it clones the DOM, apart from this everything is in react.
Initialized the jQuery nestable functionality like below:
componentDidMount() {
this.$node = $(this.nestable); // this.nestable is a ref
this.$node.nestable({
group: 1,
maxDepth: 4,
expandBtnHTML:"",
collapseBtnHTML:""
});
}
the above code will let me drag the group2 among all other DOM elements like below image:
group2 is the draggable element here.
after dragged, I can see that group2 apperaed twice and I guess jQuery plugin clones the dragged element like below:
and in developer tools :
But In react developer tools, I can see that DOM is correct.
I don't know, how to rectify this problem. I'm unable to update the full code here because the code base is large.
In react developer tools, I can see that DOM is correct, and in native DOM is not !!
Is it possible to replace native DOM by virtual DOM after setState or is it possible for react to trace DOM handled by jQuery ?
I accept # Patrick Evans comments, I'm looking for a solution here or suitable react based component like jQuery nestable.
Any help on this will be helpful.
React-nestable seems to have the same behavior as that jQuery plugin and could save you a lot of trouble. Mixing jQuery with React is super easy to cause trouble in my experience.
There is one hacky solution here:
In Nestable you have on change event. So you keep order of list as a state of component and while you drag and drop an element you can update the state and list should be re-rendered.
Please see that you can use key in list elements to optimize it a bit.
I am sure this will solve your issue.

How to do perf analysis in React 16

The React docs state that react-addons-perf does not work with React 16, but that Chrome's built-in tools provide equivalent functionality. I have not found this to be the case.
For instance, let's say that I've made the classic mistake of not including a proper key on a list of elements (demo code is on GitHub):
render() {
const items = this.state.items.map((item, index) => <ListItem key={index} name={item.name} />)
return <div>
<button onClick={this.addItem}>Add item</button>
<ul>{items}</ul>
</div>;
}
The key={index} issue will cause every ListItem to re-render when I add an item to the list. Using React 15 perf tools, I can easily discover this:
Once I apply the fix, I can see that the problem has gone away:
However, with React 16 and the Chrome dev tools, I'm not sure how to get equivalent information. (Demo code with React 16.) Here's the profiling results from when the bug was present:
And here are the profiling results from when the bug was absent:
I don't know how I'd look at these profiling results and get the same information that react-addons-perf was providing. And, my results don't look anything like the React docs:
I'm on Chrome 63.0.3239.108. Is the React team on a different version of Chrome, or do you need to enable special flags to make this work?
Potentially related: How can I measure wasted renders in React 16?.
tl;dr
How can I get useful information from the Chrome profiler?
Why do my profiler sessions look different from the React docs?
Update
Thanks Rob. M! Turns out I was looking in the wrong tab in the dev tools. When I open the User Timing section, I see the difference between the good and the bad:
Bad, with many ListItem updates:
Good, with one ListItem update:
React events are logged under the "User Timing" label - if you expand that label instead of "Main" you should find the component performance data you are looking for.

How to test with Enzyme shallow and component based UIs?

We are using the Semantic React UI library. The code often looks like:
<div className="EditTemplateMetaDataPage">
<Page title={...}>
<Container text>
<Segment>
<Grid columns={1}>
<Grid.Column>
<Button ...>
This might be interesting for many people, using similar React Component libraries like Material UI or Bootstrap React.
We currently use mount with the enzyme library instead of shallow, because we would render only one level deep
, to the first <Grid> component in a test, which is just a visual helper, while we really need the deeper buried Button instead.
Because of performance and to avoid overlapping tests it is recommended to use shallow. (We follow London school TDD, and check only that sub-components exist and their interfaces are used properly)
We came up with using CSS-only for visual components, i.e.
<div className='ui one column grid'>
instead of:
<Grid columns={1}>
But we are not sure, whether this is the optimal approach. Do you have other ideas? How can we use shallow(...) in this case?
shallow actually allow you to use your component as selector, so you can do something like
import Button from '../Button'
const page = shallow(<Page />)
expect(page.find(Button).length).toBe(1)
http://airbnb.io/enzyme/docs/api/selector.html

Categories