cozy / cozy-ui

React components and CSS styles for Cozy apps
https://cozy.github.io/cozy-ui/react/
MIT License
48 stars 37 forks source link

API changes to ViewStack #1259

Open ptbrowne opened 4 years ago

ptbrowne commented 4 years ago

Instead of pushing views, breaking the rendering flow of React (since the views are pushed imperatively instead of being declaratively rendered), I think we should use an API much more close to react-router.

const FirstScene = () => {
   const { push } = useHistory()
   return <div>
      <button onClick={() => push('category')}>edit category</button>
      <button onClick={() => push('date')}>edit date</button>
   </div>
}

const CategoryEdition = () => {
   const { goBack } = useHistory()
   return <div>editing category<button onClick={goBack}>cancel</button></div>
}

const Scene = () => {
   return <ViewStack>
      <FirstScene />
      <ViewStack.Switch>
         <ViewStack.Route route='category'>
             <CategoryEdition />
          </ViewStack.Route>
         <ViewStack.Route route='date'>
             <DateEdition />
          </ViewStack.Route>
      </ViewStack.Switch>
   </ViewStack>
}

ViewStack -> SlideNavigator ? ModalStack -> ModalNavigator ? useStack -> useNavigation ?

EDIT: changed navigate to history.push

Crash-- commented 4 years ago

In fact, since we're going pretty close to React Router, why not using something around it like https://github.com/maisano/react-router-transition or creating our transitiongroup (cf https://css-tricks.com/animating-between-views-in-react/) ?

With that in mind, what can't be done by react-router and a wrapped transition?

ptbrowne commented 4 years ago

why not using something around it like maisano/react-router-transition

Yes, I'd be willing to explore this option.

  • navigate() can be Redirect

Erratum: I was thinking of the history.push API when I wrote navigate and I think we should stick with the react-router API (I edited the original post). This being said, I think the Redirect and history.push have different usecases:

With that in mind, what can't be done by react-router and a wrapped transition?

Probably nothing.

I am only worried about the fact that we'd have to add a route for any view that is stacked. For example for modals ? Should we add a route if we want to display a modal or a simple slide transition to select a value in mobile ? Maybe. I don't see the downsides though and it would be probably help when developing since the state (being in the URL) would be kept between page reload and we would not have to click a button to open the modal we are developing.

Maybe if we do not need a route in the URL we can use a MemoryRouter, it'd be interesting to check if we can use both a HashRouter and a MemoryRouter at different places in an app.

y-lohse commented 4 years ago

I am only worried about the fact that we'd have to add a route for any view that is stacked.

One minor downside is that it would be possible to access for example a success view with the URL, without having done the previous parts. But again that's pretty minor and imo worth it for using the normal react flow and leveraging react-router.

ptbrowne commented 4 years ago

One minor downside is that it would be possible to access for example a success view with the URL, without having done the previous parts

Good point, we'll try to avoid that using a MemoryRouter 🤞

ptbrowne commented 4 years ago

One potential downside is that when you change a route, the majority of the app must re-render, it might be too expensive for animations/transitions.

ptbrowne commented 4 years ago

Other thing to take into consideration : some generic UI components for example the NestedSelect could want to use the {Modal,View}Stack without wanting to deal with routes (since they are not aware of the application routes). This is why I am think we should first try without router first and then in some cases connect it to the router.

y-lohse commented 4 years ago

I haven't coded anything yet, just learned how the different APIs and modules work etc. Here's a write-up:

There are 2 main parts:

  1. An API to control which view to show, switching between views, etc
  2. Animating from one view to another

In terms of the navigation API, some possibilities:

  1. Just a push(View)/pop(), which is the current StackView API, not very react friendly and hard to use with a router
  2. A tree declaration + custom push/pop as in the opening message of this thread. Would work well for our use cases.
  3. The react-router configuration is the view declaration, navigation is done by changing routes (ie. pluging an animation system on top of react-router). Great for app-level navigation, hard if not impossible for stand alone components
  4. Route declaration through a config object, navigating via custom push/pop functions (aka. react-navigation). More or less the same as number 2. But I don't think we can easily plug react-navigation into a react-router, navigation seems to be programmatic only.

In terms of animations, I don't think there's a way around either adding animation custom code (eg. react-transition-group) or adding specific animation libs (like react-swipeable-views). To add a grow animation for example, we probably need to introduce a GrowView wrapper in which react-swipeable-view is replaced by a transition group.

That's all for now, i have to digest this a bit before I start coding something.