React-native-web: Components backlog

Created on 10 Mar 2016  路  35Comments  路  Source: necolas/react-native-web

  • [ ] Modal
  • [ ] RefreshControl
  • [ ] Slider
  • [ ] TouchableNativeFeedback
  • [ ] WebView
  • [x] Button
  • [x] CheckBox
  • [x] FlatList
  • [x] ImageBackground
  • [x] ListView
  • [x] Picker
  • [x] SectionList
  • [x] ProgressBar
  • [x] ScrollView
  • [x] SwipeableFlatList
  • [x] SwipeableListView
  • [x] Switch
  • [x] Touchable
  • [x] VirtualizedList

PR's welcome

Most helpful comment

If you want to add support for a feature manually you can update the webpack config alias from

alias: {
 'react-native': 'react-native-web'
}

to

alias: {
  'react-native': path.resolve(__dirname, './custom-react-native-web.js')
}

with the following file content for custom-react-native-web.js:

const RNWeb = require('react-native-web')

// add any component override here:
// note the .default for ES6 libraries
RNWeb.Modal = require('react-native-web-modal').default 

module.exports = RNWeb

This makes other libraries that use modals automatically compatible with web 馃憤

All 35 comments

Are you accepting PRs for any of these?

Yep

@necolas I started on an initial version of FlatList since I needed it for my own project. It's rather simple as I'm not using VirtualizedList or anything fancy under the hood. It also doesn't support all of the props, just the main ones for now as that's all I needed. Is something like this worth commiting to this repository?

/* @flow */

import * as React from 'react';

import type { StyleFlowType } from '../../../types/style';
import { ScrollView, View } from 'react-native-web';

type PropsFlowType = {
  ItemSeparatorComponent?: React.ComponentType<any>,
  ListFooterComponent?: React.ComponentType<any>,
  ListHeaderComponent?: React.ComponentType<any>,
  contentContainerStyle?: StyleFlowType,
  data?: Array<any>,
  horizontal?: boolean,
  keyExtractor?: (item: any) => string,
  renderItem: (obj: { index: number, item: any }) => ?React.Element<any>,
  style?: StyleFlowType,
};

const FlatList = ({
  ItemSeparatorComponent,
  ListFooterComponent,
  ListHeaderComponent,
  contentContainerStyle = {},
  data = [],
  horizontal = false,
  keyExtractor,
  renderItem,
  style = {},
}: PropsFlowType = {}): React.Node => (
  <ScrollView
    contentContainerStyle={contentContainerStyle}
    horizontal={horizontal}
    style={style}
  >

    {ListHeaderComponent &&
      <ListHeaderComponent />
    }

    {data.map((item, index): React.Node => (
      <View
        key={keyExtractor ? keyExtractor(item) : index}
      >

        {renderItem({ index, item })}

        {(ItemSeparatorComponent && index < data.length - 1) &&
          <ItemSeparatorComponent />
        }

      </View>
    ))}

    {ListFooterComponent &&
      <ListFooterComponent />
    }

  </ScrollView>
);

export default FlatList;

Thanks but I don't think so

Is work ongoing anywhere to create FlatList, SectionList, VirtualizedList, etc.?

@Connorelsea see this PR to bring in Virtualized List: https://github.com/necolas/react-native-web/pull/474

Is there an easy way we can already mock out some of these components? I'm using a Modal and I especially want to implement the "visible" prop, the rest is way less important to me at the moment

At my company we are willing to maintain this project and contribute with code because we depend on it. They have proposed me to do a fork but I'm not willing to do it and I preffer to have all our changes upstream. If maintainers are busy at this moment to review and accept pull-requests, could you be able to give me push permissions so I can move it forward?

I'm not too busy to review PRs. But some PRs are so far off being good enough that I basically need to rewrite them myself :)

Some of them like modal or WebView can use third-party dependencies...

I can confirm that the iOS polyfill for native DrawerLayoutAndroid component works on react-native-web too, so it could be added as a dependency and exported as an aditional component.

I could be able to do a pull-request for that, what would be the correct name it should be exported? DrawerLayout as a generic one, DrawerLayoutAndroid like the currently available on react-native (although it would not be Android specific anymore, or maybe like both?

@piranna Did your company end up doing a fork?

@piranna Did your company end up doing a fork?

Still not, we have been able to find workarounds for own issues.

@necolas i'm correct to think the Picker code you added is still a stub right. As far as i can tell i cannot yet add picker components (for web) based on what's in master now..?

Picker is in master - https://github.com/necolas/react-native-web/blob/master/src/components/Picker/index.js. Will be in the next minor release

I think https://github.com/Flipkart/recyclerlistview can replace Lists in web until we don't have original lists components.

@necolas, would you accept pull-request using dependencies? Almost all the missing APIs and components have some compatible implementation like Modal, Lists and WebView, it would just be a matter of use them as dependencies and export them so there would not be need of doing hacks to use them, and also you would not need to maintain their code... So far we are having dificulties to use https://github.com/n4kz/react-native-material-dropdown because it makes usage fo Modal, and point is support is added on react-native-web (yours or on a pull-request), or we would need to modify that library in a custom and incompatible way... :-/

A drop in Modal replacement is https://www.npmjs.com/package/react-native-web-modal.

I modified @joncursi's FlatList implementation to be more compatible with the default FlatList https://gist.github.com/grit96/26d17a508525c248617546d5ca0d0fef.

Thank you @grit96 !

If you want to add support for a feature manually you can update the webpack config alias from

alias: {
 'react-native': 'react-native-web'
}

to

alias: {
  'react-native': path.resolve(__dirname, './custom-react-native-web.js')
}

with the following file content for custom-react-native-web.js:

const RNWeb = require('react-native-web')

// add any component override here:
// note the .default for ES6 libraries
RNWeb.Modal = require('react-native-web-modal').default 

module.exports = RNWeb

This makes other libraries that use modals automatically compatible with web 馃憤

Nice trick @EyMaddis! Kudos! :-D

@necolas by the looks of the post at the top, FlatList and SectionList are not yet supported. is this going to happen please? If so do you have an ETA. I tried to use FlatList and Section but nothing gets displayed :(

@IncredibleMrTim you can use a custom implementation of the FlatList (here) using the details provided by @EyMaddis above.

For anybody interested, based on the @EyMaddis sugestion I've developed a wrapper module that piggy-backs on top of react-native-web and add the missing APIs and Components, so there's no need to do tricks like aliasing individual components. So far, except TouchableNativeFeedback and the deprecated Navigator and NavigatorIOS, all the components from React Native are available by using third-party modules.

Comments, pull-requests and any help are welcome :-)

Yay.. Finally react-native is almost true cross platform framework. Great work Mr.@piranna.
The only thing that needs to done now is get react-navigation to work in web properly then almost any react-native app will work in the web.

The only thing that needs to done now is get react-navigation to work in web properly then almost any react-native app will work in the web.

Well, in fact, one of the dependencies I'm using is a previous effort called react-native-web-extended that has a Navigator component, but since the project is abandoned since a year ago and was developed as a fork, I did a pull-request isolating the extra components and updating the dependencies, and doing so I found that it was developed using react-router and that Navigator was deprecated on React Native 0.44 just to recomend people to use react-router and only left NavigatorIOS for projects focused only for iOS, so since I was having problems upgrading react-router I removed both components. If you are interested in have Navigator or NavigatorIOS, you can pick the old code and try to update it and publish as an independent package, and I'll add it as a dependency :-)

On the other hand, my wrapper still needs some work, for example there's a bug on art package that prevent it to be used server-side so tests don't pass (fixing the bug they do, and it works on production on a web browser), and also needs some tune-ups to make it fully work correctly with babel-plugin--react-native-web module.

FlatList has a little tick next to it in the above list, but all I'm getting in a div with a red border. Is it still yet to be implemented?

@necolas do you have an up to date list of available components that can be used with RNW please?

Regarding react-navigation. We have been successfully using it up to version 1.5.12. The new 2.x releases don't work. To use 1.5.12 we do the following:

  1. Create a webpack alias like this:
      "react-navigation": "react-navigation/src/react-navigation.js",
  1. We run a simple fix in yarn's postInstall:
if [ ! -f ./node_modules/react-navigation/src/PlatformHelpers.js ]; then
  mv ./node_modules/react-navigation/src/PlatformHelpers.native.js ./node_modules/react-navigation/src/PlatformHelpers.js
fi

Then react-navigation works pretty well. One other fix I did was to hide off-screen stuff by implementing a custom transition:

    transitionConfig: (): {} => {
      if (Platform.OS !== 'web') return {};
      /**
       * A custom `transitionSpec` is used here to for the web
       * transitions in order "hide" content not on the top
       * of the screen for 508/Accessibility reasons
       */
      return {
        transitionSpec: {
          duration: 300,
          easing: Easing.out(Easing.poly(4)),
          timing: Animated.timing
        },
        screenInterpolator: (sceneProps: NavigationSceneRendererProps): {} => {
          const { layout, position, scene } = sceneProps;
          const { index, isActive } = scene;

          const width = layout.initWidth;
          const translateX = position.interpolate({
            inputRange: [index - 1, index, index + 1],
            outputRange: [width, 0, 0]
          });

          const opacity = position.interpolate({
            inputRange: [index - 1, index - 0.99, index],
            outputRange: [0, 1, 1]
          });

          return {
            opacity,
            transform: [{ translateX }],
            visibility: isActive ? 'visible' : 'hidden'
          };
        },
        headerLeftInterpolator: (headerProps: NavigationSceneRendererProps): {} => {
          const { isActive } = headerProps.scene;
          return {
            visibility: isActive ? 'visible' : 'hidden'
          };
        },
        headerRightInterpolator: (headerProps: NavigationSceneRendererProps): {} => {
          const { isActive } = headerProps.scene;
          return {
            visibility: isActive ? 'visible' : 'hidden'
          };
        }
      };
    }

This will add the visibility: hidden where needed and makes keyboard navigation possible.

You might want to surface issues with react navigation on their repo /cc @brentvatne.

Closing this and tracking the remaining components in #1025 #1024 #1022 #1020 #1027

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ndbroadbent picture ndbroadbent  路  3Comments

necolas picture necolas  路  3Comments

ricklove picture ricklove  路  3Comments

holmesal picture holmesal  路  3Comments

roryabraham picture roryabraham  路  3Comments