popToRoute() not working when I pass in route object - navigator

I've googled this a bunch and there aren't sufficient examples or explanations that tell me how popToRoute(), the react-native navigator method exactly works. Would be awesome if someone could help me better understand it.
I'm passing in my route object (which is definitely correct) but get the error: "Invariant Violation: Calling popToRoute for a route that doesn't exist!"
Here is the relevant code where I use the popToRoute() navigator method:
var InviteRoommates = React.createClass({
submitRoommates: function() {
this.props.navigator.popToRoute({
index: 3,
id: 'ItemList'
});
},
render: function() {
return (
<View style={styles.container}>
<Text>INVITE ROOMMATES</Text>
<TextInput style={styles.input} placeholder="roommate's email address"/>
<TouchableHighlight
style={styles.button}
onPress={() => this.submitRoommates()}
>
<Text style={styles.btnText}>Submit</Text>
</TouchableHighlight>
</View>
);
}
});

I wrote the exact same code as you, have the same problem. Found a solution that works, although ugly. Access all the route objects with this.props.navigator.getCurrentRouts(), then specifying one by it's index in the array. Of course this only works if you know the route object's position in the stack at all times....
this.props.navigator.popToRoute(this.props.navigator.getCurrentRoutes()[1]);

If you want to popToRoute by name you can simply loop through the route stack and check each route by name, then pop to that route.
var routes = this.props.navigator.state.routeStack;
for (var i = routes.length - 1; i >= 0; i--) {
if(routes[i].name === "MyDestinationRoute"){
var destinationRoute = this.props.navigator.getCurrentRoutes()[i]
this.props.navigator.popToRoute(destinationRoute);
}
}

This worked for me.
const routes = this.props.navigator.getCurrentRoutes();
const routeToGo = routes.find( route => route.name == 'the name of the route');
this.props.navigator.popToRoute(routeToGo);

Related

Execute a function based on a specific scroll position in React native

I am trying to call an api base on scroll View current position but not sure how to I achieve that.
This is my code
<ScrollView
ref={scrollViewRef}
scrollEventThrottle={0}
onScroll={({nativeEvent}) => {
console.log(
nativeEvent.contentSize.height -
nativeEvent.layoutMeasurement.height,
);
console.log(nativeEvent.contentOffset);
}}>
I tried to call the api inside onScroll but that didnt work well.
Try adding an event listener at the particular scroll location you want the function to execute.
useEffect(() => {
Window.addEventListener(‘scroll’_.debounce(setScroll,1000));},[]);
I have solved the issue by using adding an if check. If the api data exist then the function wont execute anymore.
here's the code
const [apiData, setApiData] = useState();
onScroll={({nativeEvent}) => {
if (!apiData) {
if (
nativeEvent.contentSize.height -
nativeEvent.layoutMeasurement.height -
nativeEvent.contentOffset.y <
250
) {
getApiDataHandler();
}
}
}}

Populte WYSIWYG editor after react native fetch

I am trying to incorporate this WYSIWYG package into my react native project (0.64.3). I built my project with a managed workflow via Expo (~44.0.0).
The problem I am noticing is that the editor will sometimes render with the text from my database and sometimes render without it.
Here is a snippet of the function that retrieves the information from firebase.
const [note, setNote] = useState("");
const getNote = () => {
const myDoc = doc(db,"/users/" + user.uid + "/Destinations/Trip-" + trip.tripID + '/itinerary/' + date);
getDoc(myDoc)
.then(data => {
setNote(data.data()[date]);
}).catch();
}
The above code and the editor component are nested within a large function
export default function ItineraryScreen({route}) {
// functions
return (
<RichEditor
onChange={newText => {
setNote(newText)
}}
scrollEnabled={false}
ref={text}
initialFocus={false}
placeholder={'What are you planning to do this day?'}
initialContentHTML={note}
/>
)
}
Here is what it should look like with the text rendered (screenshot of simulator):
But this is what I get most of the time (screenshot from physical device):
My assumption is that there is a very slight delay between when the data for the text editor is actually available vs. when the editor is being rendered. I believe my simulator renders correctly because it is able to process the getNote() function faster.
what I have tried is using a setTimeOut function to the display of the parent View but it does not address the issue.
What do you recommend?
I believe I have solved the issue. I needed to parse the response better before assigning a value to note and only show the editor and toolbar once a value was established.
Before firebase gets queried, I assigned a null value to note
const [note, setNote] = useState(null);
Below, I will always assign value to note regardless of the outcome.
if(data.data() !== undefined){
setNote(data.data()[date]);
} else {
setNote("");
}
The last step was to only show the editor once note no longer had a null value.
{
note !== null &&
<RichToolbar
style={{backgroundColor:"white", width:"114%", flex:1, position:"absolute", left:0, zIndex:4, bottom: (toolbarVisible) ? keyboardHeight * 1.11 : 0 , marginBottom:-40, display: toolbarVisible ? "flex" : "none"}}
editor={text}
actions={[ actions.undo, actions.setBold, actions.setItalic, actions.setUnderline,actions.insertLink, actions.insertBulletsList, actions.insertOrderedList, actions.keyboard ]}
iconMap={{ [actions.heading1]: ({tintColor}) => (<Text style={[{color: tintColor}]}>H1</Text>), }}
/>
<RichEditor
disabled={disableEditor}
initialFocus={false}
onChange={ descriptionText => { setNote(descriptionText) }}
scrollEnabled={true}
ref={text}
placeholder={'What are you planning to do?'}
initialContentHTML={note}
/>
}
It is working properly.

Unable to get renderStepIndicator working on react-native-step-indicator

I think I am not understanding the documentation correctly.
The documentation says: that is takes a Function that return a position: Number, or a stepStatus: which takes a String to render custom content inside step
My goal is to render a check mark instead of a number as it is by default.
I tried to return a string of 'test' and it does not work.
<StepIndicator
customStyles={customStyles}
currentPosition={this.state.currentPosition}
stepCount={this.state.stepCount}
renderStepIndicator={() => {
this.renderStepIndicator();
}}
labels={labels}
/>
and this is the function that return a string
renderStepIndicator() {
return 'test';
}
I am not sure what I am missing here. also I want to return an icon of checkmark. I have seen people doin git but I am not sure how if this only takes a string or an integer.
Here this function returns two parameters step position and step status. You can use this function like this,
<StepIndicator
customStyles={customStyles}
currentPosition={this.state.currentPosition}
stepCount={this.state.stepCount}
renderStepIndicator={(stepPosition,stepStatus) => {
this.renderStepIndicator(stepPosition,stepStatus);
}}
labels={labels}
/>
And the render function is like,
renderStepIndicator(stepPosition, stepStatus) {
return <Icon name={"check"} size={20} color={stepStatus === 'finished' ? "green" : "gray"} /> ;
}
This function render check icon. If you step was complete it show green check otherwise gray check.
For more details you can check this example,
https://github.com/24ark/react-native-step-indicator/blob/master/example/src/HorizontalStepIndicator.tsx
The above solution does not work for me so tried some changes and after some time I got this working solution if some are still facing this issue try using this code.
1. Put this code in your StepIndicator props
renderStepIndicator={({ position, stepStatus }) =>
renderStepIndicatorRender(position, stepStatus)
}
2. Create a function to render the icon
const renderStepIndicatorRender = (stepPosition, stepStatus) => {
return stepStatus === "finished" ? (
<Icon name="check" size={12} color="#fff" />
) : (
<Text>{stepPosition}</Text>
);

Creating a checkbox group with React Native

Good Morning! I am wanting to create a selection box where the user has several options of items to choose from and when clicking on a button, it triggers a function that shows all the values that the user chose in the form of an array, json or even arrays ( hard task).
In the React Native documentation, only simple examples of checkboxes using the component are provided and I wanted to go much further than the documentation provides me. What are the possible solutions to this problem? (from a simpler example to an advanced one) and what (s) ways can I explore this problem in order to solve it in the most practical and uncomplicated way?
Definitions and examples of official documentation:
https://reactnative.dev/docs/checkbox/ (CheckBox)
https://reactnative.dev/docs/button/ (Button)
With this problem, another one came up: build an application where the user selects shopping options (items) and a subtotal is displayed in the lower corner of the application as he selects or deselects the items he is going to buy, and there is also an option to reset the subtotal by returning it to the zero value.
From the problem mentioned at the beginning, what are the possible solutions to create this application previously mentioned in a practical and simple way?
Multi Checkbox example ( Updated with Hook )
export const Example = () => {
const [checkboxes, setCheckboxes] = useState([{
id: 1,
title: 'one',
checked: false,
}, {
id: 2,
title: 'two',
checked: false,
}]);
const onButtonPress = () => {
const selectedCheckBoxes = checkboxes.find((cb) => cb.checked === true);
// selectedCheckBoxes will have checboxes which are selected
}
const toggleCheckbox = (id, index) => {
const checkboxData = [...checkboxes];
checkboxData[index].checked = !checkboxData[index].checked;
setCheckboxes(checkboxData);
}
render(){
const checBoxesView = checkboxes.map((cb, index) => {
return (
<View style={{flexDirection:"row"}}>
<Checkbox
key={cb.id}
checked={cb.checked}
onPress={() => toggleCheckbox(cb.id, index)} />
<Text>{cb.title}</Text>
</View>
);
});
return (
<View>
{ checBoxesView }
<Button onPress={onButtonPress} title="Click" />
</View>
);
}
}

React Native. Filter FlatList - error "index=10 count 0"

My task is to filter some array and set it to FlatList.
My filter function is:
updateInvoiceList = (text) => {
let invoiceList = [...this.state.baseInvoiceList];
invoiceList = invoiceList.filter(el => {
return el.name.toLowerCase().includes(text.toLowerCase())
});
this.setState({invoiceList})
}
After filtering, I provide state.invoiceList to FlatList and everything works correctly. But, when I set some symbol which does not exist in my array, for example "!", the function clears the array and it still behaves correctly. When I remove the symbol "!", I get an error screen with:
index=10 count=0
addInArray
ViewGroup.java:5235
addViewInner
ViewGroup.java:5128
addView
ViewGroup.java:4935
addView
ReactViewGroup.java:452
addView
ViewGroup.java:4875
addView
ReactViewManager.java:269
addView
ReactViewManager.java:36
manageChildren
NativeViewHierarchyManager.java:346
execute
UIViewOperationQueue.java:227
run
UIViewOperationQueue.java:917
flushPendingBatches
UIViewOperationQueue.java:1025
access$2600
UIViewOperationQueue.java:46
doFrameGuarded
UIViewOperationQueue.java:1085
doFrame
GuardedFrameCallback.java:29
doFrame
ReactChoreographer.java:166
doFrame
ChoreographerCompat.java:84
run
Choreographer.java:964
doCallbacks
Choreographer.java:790
doFrame
Choreographer.java:721
run
Choreographer.java:951
handleCallback
Handler.java:883
dispatchMessage
Handler.java:100
loop
Looper.java:214
main
ActivityThread.java:7356
invoke
Method.java
run
RuntimeInit.java:492
main
ZygoteInit.java:930
What did I do wrong?
I had the exact same issue with my code, inside a Flatlist and only showing up on Android. I've managed to solve it as follows:
My FlatList had
stickyHeaderIndices={this.state.items[1]}
but apparently the List was loading that stickyHeader ahead of its initialization. From here, the solution consists simply in handling the case in which that item is not initialized yet.
stickyHeaderIndices={this.state.items.length > 0 ? [1] : [0]}
Hope this helps! The solution is pretty straightforward. Debugging it can be a real pain, tho!
On Android, you must not initialise your FlatList stickyHeaderIndices with empty array.
Instead, when your state is not loaded yet, provide FlatList data with some initial data and provide stickyHeaderIndices with [0]
Example code as below
let [data, stickyIndices] = someAPIToGetYourData()
...
...
...
// if your data is not finished loading yet
if (data.length === 0) {
// create not-empty array
data = getInitialNotEmptyData()
// add not-empty index
headerIndexList = [0]
}
return (
<SafeAreaView>
<FlatList
data={data}
stickyHeaderIndices={headerIndexList /* This must not be empty */ }
renderItem={item => renderYourItem(item)}
/>
</SafeAreaView>
)
Hope this help!
I needed kill the FlatList to fix this error, like this:
<View>
{ this.state.data.length > 0 &&
<FlatList
showsVerticalScrollIndicator={false}
refreshing={false}
onRefresh={() => this.onRefresh()}
data={this.state.data}
extraData={this.state}>}
</View>
Hope this helps!
LayoutAnimation causes a similar issue, not only with Flatlist but any kind of lists, check if you are using it in your app and if you have UIManager.setLayoutAnimationEnabledExperimental(true) on your top component, removing it might fix your issue, but will disable the layoutAnimations.
You might find more information here and here
Please improve your function.
updateInvoiceList = (text) => {
let invoiceList = [];
const { baseInvoiceList } = this.state;
if(text){
invoiceList = baseInvoiceList.filter(item => {
return item.name.toLowerCase().includes(text.toLowerCase());
});
}
this.setState({invoiceList});
}