Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Redirects not working as expected #100

Closed
ramnivas opened this issue Apr 8, 2015 · 8 comments
Closed

Redirects not working as expected #100

ramnivas opened this issue Apr 8, 2015 · 8 comments

Comments

@ramnivas
Copy link
Contributor

ramnivas commented Apr 8, 2015

Context: https://gitter.im/japgolly/scalajs-react?at=5524ad269f817500153c209b

To produce a minimized example that shows a problem with interceptRender and redirect, I tried the following code (the original project uses Flux and all that, so a bit complex to explain). But redirect isn't working for me. Is my use of redirect correct or does this show an issue with scalajs-react?

I expected that when I click on the Login button, it should show the private page content and the url to be /private. But I don't see any change.

package example

import japgolly.scalajs.react.extra.router.Redirect.Replace
import japgolly.scalajs.react.extra.router.{BaseUrl, Redirect, RoutingRules}

import scala.scalajs.js
import js.annotation.JSExport
import org.scalajs.dom

import scala.scalajs.js

import japgolly.scalajs.react._
import vdom.all._

@JSExport("Main")
object ScalaJSReactExample extends js.JSApp {
  def main(): Unit = {
    val baseUrl = BaseUrl.fromWindowOrigin + "/"

    val router = MainRouter.router(baseUrl)

    React.render(router(), dom.document.body)
  }
}

object MainRouter extends RoutingRules {
  val root = register(rootLocation(PublicPage.Component(())))
  val pvt = register(location("private", PrivatePage.Component(())))

  override protected val notFound = redirect(root, Redirect.Replace)

  register(removeTrailingSlashes)

  override protected def interceptRender(ic: InterceptionR): ReactElement = {
    println(s"Intercepting")
    if (AuthenticationStore.authenticated) {
      div(
        div(
          button(onClick --> {println("Logging out"); AuthenticationStore.authenticated = false; redirect(root, Replace)})("Logout")
        ),
        ic.element
      )
    } else {
      div(
        div(
          button(onClick --> {println("Logging in"); AuthenticationStore.authenticated = true; redirect(pvt, Replace)})("Login")
        ),
        ic.element
      )
    }
  }
}

object AuthenticationStore {
  var authenticated = false
}

object PublicPage {
  val Component = ReactComponentB[Unit]("Public").render(_ => div("Public")).build
}

object PrivatePage {
  val Component = ReactComponentB[Unit]("Private").render(_ => div("Private")).build
}
@japgolly
Copy link
Owner

Ah that's not going to work. In this bit here:

button(onClick --> {println("Logging in"); AuthenticationStore.authenticated = true; redirect(pvt, Replace)})("Login")

you're calling redirect. You have to remember that you're inside RoutingRules here so redirect isn't an action that you can execute, it's DSL for creating dynamic routing rules (which is why 1) it's protected, and 2) it returns DynAction which is Path => RouteAction[P]).

You need to redirect like you normally would outside the RoutingRules class. In your interceptRender(ic: InterceptionR), call .router on your ic arg and use that.

@japgolly
Copy link
Owner

To be clear, something like this:

button(onClick --> {println("Logging out"); AuthenticationStore.authenticated = false; ic.router.setIO(root).unsafePerformIO() })("Logout")

@ngbinh
Copy link

ngbinh commented Apr 22, 2015

also, I don't think it will work because even though you are redirecting the route, you still return the component for the current route. So you probably need to replace ic.element with a different one.

@japgolly
Copy link
Owner

japgolly commented Apr 22, 2015 via email

@ngbinh
Copy link

ngbinh commented Apr 22, 2015

@japgolly Oh right! I miss that part.

@ramnivas
Copy link
Contributor Author

Works after implementing @japgolly suggestion. Thanks!

@gabadi
Copy link

gabadi commented May 1, 2015

I've used @japgolly implementation, but i've got an error:

Uncaught Error: Invariant Violation: removeComponentAsRefFrom(...): Only a ReactOwner can have refs. This usually means that you're trying to remove a ref to a component that doesn't have an owner (that is, was not created inside of another component's render method). Try rendering this component inside of a new top-level component which will hold the ref.

Does someone have the same error?

@gabadi
Copy link

gabadi commented May 1, 2015

I'm sorry, i've solved it
I had a problem in my router, but i don't know exactly what.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants