How add a 404/Catch all navigation Routes in Jetpack Compose - kotlin

I have several routes that are not yet implemented fully but need to have buttons/links defined.
How I can get a "404" route that display them instead of crashing?
NavHost(
navController = nav,
startDestination = NavRoutes.Splash.route,
) {
composable(NavRoutes.Home.route) {
To(nav = nav, Request.Home(ctx = ctx))
}
// How have this?
composable(NavRoutes.Errors.404) {
To(nav = nav, Request.Error(route = ???))
}
}

Related

​ [Kotlin/JS with React] Is there a way to use React Portals?

The function I suppose I should use is:
createPortal(
children: ReactNode?,
container: Element,
key: Key? = definedExternally,
)
What I tried is doing something like this:
A component (Modal.kt)
val Modal = FC<Props> {
p {
+"A model modal"
}
}
Then in the main App component:
val App = FC<Props> {
val modalContainer = document.getElementById("menu-root") ?: error("Couldn't find menu root container!")
createPortal(Modal.create(), modalContainer)
}
And in the main method:
fun main() {
val container = document.getElementById("root") ?: error("Couldn't find root container!")
createRoot(container).render(App.create())
}
This doesn't work however. I've tried writing something akin do what you'd write in vanilla React:
In Modal.kt
val modalContainer = document.getElementById("modal-root") ?: error("Couldn't find modal root!")
val modalComponent = FC<Props> {
p {
+"A model modal"
}
}
val Modal = createPortal(
modalComponent.create(),
modalContainer
)
And in the main App component:
val App = FC<Props> {
+Modal // Is of type ReactPortal, so you can't invoke it like a function
}
This doesn't work, however, so I feel pretty stuck. Would anybody be able to provide insight into this? It would be greatly appreciated!

How to make a button a menu trigger in Jetpack Compose?

I tried adding an IconButton() and wanted to click the button to turn it on or off (while also clicking elsewhere to dismiss it)
But a funny qustion happend.
The trigger button is included in "Other Places", when I click the button to close the menu, this triggers onDismissRequest() first, and then triggers the button's onClick(), which makes me unable to close the menu (when clicked will instantly close and then open again)
Scaffold(
...
topBar = {
TopAppBar(
...
actions = {
var menuExpanded by remember { mutableStateOf(false) }
Box {
IconButton(onClick = { menuExpanded = !menuExpanded}) {
Icon(
painter = painterResource(id = R.drawable.menu),
contentDescription = "menu",
tint = white
)
}
DropdownMenu(
expanded = menuExpanded,
properties = PopupProperties(),
onDismissRequest = { menuExpanded = false }
) {
// items
}
}
}
)
}
) { ... }
I know I can set Modifier.offset() so that menu masks the button, but I don't want to do that.
What should I do?
This is what PopupProperties.focusable is for: true value prevents other views from getting tapped while the menu is open. By the way, this is the default value if you don't specify properties option.
DropdownMenu(
expanded = menuExpanded,
properties = PopupProperties(focusable = true),
onDismissRequest = { menuExpanded = false }
) {

How do I change the variable value in a different file in Swiftui

I set a variable in the contentview #State var shouldShowModal = false, i want to change it once i press a button shouldShowModal = false. I keep getting Cannot find 'shouldShowModal' in scope.
Here is a working example, passing the value through #Bindings. Read more about #Binding here, or the official documentation.
This means that you can now do shouldShowModal = false with the binding, which will also update the body of the original view containing #State.
struct ContentView: View {
#State private var shouldShowModal = false
var body: some View {
VStack {
Text("Hello world!")
.sheet(isPresented: $shouldShowModal) {
Text("Modal")
}
OtherView(shouldShowModal: $shouldShowModal)
}
}
}
struct OtherView: View {
#Binding var shouldShowModal: Bool
var body: some View {
VStack {
Text("Should show modal: \(shouldShowModal ? "yes" : "no")")
Toggle("Toggle modal", isOn: $shouldShowModal)
}
}
}

Method from other route affects current route

I have to 2 router view - Home.vue and List.vue. Home is the index and list is the other page.
From home I navigate to list page, then I have a method that displays 10 items.
scrolled() {
var self = this
var pageHeight = document.documentElement.offsetHeight,
windowHeight = window.innerHeight,
scrollPosition =
window.scrollY
|| window.pageYOffset
|| document.body.scrollTop + (document
.documentElement && document.documentElement.scrollTop || 0);
if (pageHeight <= windowHeight + scrollPosition) {
// code to display data
self.currentPage = self.currentPage + 1
self.getGameHistory(self.currentPage)
}
}
If scrolled to the bottom it will display 10 new items. Going back to home page the method is still working upon scrolling. I don't why it happens.
Is there a way to disable that method upon changing to other route?
Assuming, you are using scrolled event listener on window object using your mounted() lifecycle method, you must de-register the global event listener on window object:
const opts = {
mounted() {
window.addEventListener('scroll', this.scrolled);
},
beforeDestroy() {
// UN-REGISTER THE GLOBAL HANDLER BEFORE COMPONENT IS DESTROYED
window.removeEventListener('scroll', this.scrolled);
},
method: {
scrolled() {
/* Your Logic */
}
}
};

React Navigation: receiving 'undefined' with this.props.navigation.state.params

I have a strange problem when I am passing props down to another screen.
I am passing two parameters; title and body, to ArticleBody screen.
class ListButtonWrapper extends React.Component {
constructor(props){
super(props);
this.articleSelected = this.articleSelected.bind(this);
}
articleSelected() {
this.props.navigation.navigate('ArticleBody', {
title: this.props.title,
body: this.props.body
});
}
When the button is pressed, it should pass those props to the next screen. And it does!
class ArticleBody extends React.Component {
render() {
const { params } = this.props.navigation.state;
const { title } = params ? params.title : null;
const { body } = params ? params.body : null;
console.log(title, body, params.title, params.body);
return (
<View>
<Text>Title: {title}</Text>
<Text>Body: {body}</Text>
</View>
);
However, calling {title} or {body} in <Text> doesn't show anything. Using console.log reveals that {title} and {body} are undefined.
However! If I use params.title or params.body, both show up as they should. But, according to the documentation, calling title or body should work.
But, here's another problem. If I change const { title } = params ? params.title : null; to const { title } = params.title it still shows up as undefined when I call title
I'm stumped. So far I can call params.title or params.body directly, but it should be working in the defined variables as well, right?
What am I doing wrong?
UPDATE
Want to add a little update. If I console.log this.props.navigation.state, I see that the props are being passed down to ArticleBody. Here is the log:
{params: {…}, key: "id-1519274761934-2", routeName: "ArticleBody"}
key: "id-1519274761934-2"
params:
body:"more stuff"
title:"stuff"
__proto__
Object
routeName:"ArticleBody"
__proto__
Object
The issue is with your code
const { title } = params ? params.title : null;
const { body } = params ? params.body : null;
The ternary condition is deciding which object you're trying to do a destructuring assignment on. In your case it's either the params.title or params.body. So your actually becomes
title = params.title.title
body = param.body.body
You should either use
const { title, body } = params ? params: null;
or
const title = params ? params.title: null;
const body = params ? params.body : null;
use props.route instead of props.navigation
If using react-navigation v5 "getParam" is deprecated, so
the same thing can be achieved using the optional chaining and nullish coalescing operators:
const data = navigation.getParam('someParam', 'defaultValue');
is equivalent to:
const data = route.params?.someParam ?? 'defaultValue';