peacechen / react-native-modal-selector

A cross-platform (iOS / Android), selector/picker component for React Native that is highly customizable and supports sections.
MIT License
369 stars 129 forks source link

Inconsistencies in selectedItemTextStyle #175

Open rpattcorner opened 2 years ago

rpattcorner commented 2 years ago

The selectedItemTextStyle property kindly added by @mikaello in #82 is exactly what my app needs, to let users who revisit a modal selector know what the currently selected value is.

However the property appears to show some odd behaviors. On a SampleApp modified only to add: selectedItemTextStyle = {{color: 'red', textDecorationLine: 'underline'}} at the beginning of the first three ModalSelector.

Here's some samples of anomalies I've seen:

Action: Open a modal, make a selection, reopen modal and see if it is highlighted by the passed TextStyle

Root case: A selection (Cherries) in the first Modal behaves as expected, showing 'Cherries" highlighted in the displayed list

Anomaly 1 Immediately repeat with the second Modal selecting 'Cranberries'. Selection is not highlighted in displayed list, suggesting either an error in that invocation or some shared state

Anomaly 2 Immediately repeat action with Modal 1 . The 'Cherries' highlight is gone. Reselect 'Cherries'

Reselect Modal 1 - 'Cherries' highlight is restored

Anomaly 3 - Retest Modal 2 entering 'Cranberries'. Modal 2 is now functioning, showing a highlighted 'Cranberries'. Interestingly if you use a different style in Anomaly 3 you'll see that the correct local style is displayed, suggesting that if there's shared state between the Modals it isn't total in any way

Anomaly 4 - Move on to Modal 3 (the switch) in the current state. Select 'Pink Grapefruit'. Reopen - 'Pink Grapefruit' is highlighted. Now revisit Modals 1 and 2. They are undisturbed, showing highlights on 'Cherries' and 'Cranberries' respectively. All appears to be working ...

So ... to me it looks like there's some kind of interaction between components. But it's not across all attributes and it has an odd pattern. Can anyone give any insight into this, or duplicate it ?

rpattcorner commented 2 years ago

So ... after more than a little digging, the real inconsistency seems to be that selectedItemTextStyle works at all outside of the default scenario. Specifically the code in index.ts sez:

let component = optionComponent || (
          <Text style={[styles.optionTextStyle,this.props.optionTextStyle,isSelectedItem && this.props.selectedItemTextStyle]} {...this.props.optionTextPassThruProps}>
              {optionLabel}
          </Text>
        );

Which, if I read the condensed syntax aright, says "If there's a custom component render it (without any respect to highlighting selected), otherwise render this fixed text component"

If this is right, one mystery is why any highlighting worked at all outside of the default case. Clearly only the fixed element respects the SITS property.

The other mystery is why the Wrapper scenario is treated as a custom component, and how that might be changed. In the "Wrapper" case we can display a wrapped icon to activate the modal instead of a text button as in the default.

For some reason the wrapper case gets treated as a custom component in the code, even though what's wrapped is not a data element component, but rather an activator to open the modal. That seems odd, and I haven't found where that happens yet. I wonder if that's intended? After all, an activator component doesn't seem to imply that the rendered data items in the modal are anything other than garden variety elements as with the default case.

Another approach might be to modify the default case to provide an icon instead of a text element. I've forced that as an experiment, and gotten the desired result of highlighting selected while activated by an Icon, but there are challenges in passing the specifics of the activator icon to the component.

rpattcorner commented 2 years ago

A final failed attempt ... looks like the state of the modal goes back to the default "initValue" even though the code in onChange(item) clearly sets selected to the just selected value. So when the modal reopens, and tries to find its selected item, it's back to the default. I suppose one could preserve the "last selected item" key in the calling code and find a way to inject it into the Modal's state on reopening, but that's just a bridge too far.

If there's something simple and obvious to implement this function, do please leave a note.