🎃

React Native for WebのViewの実装読んでみた

2022/03/09に公開

友達と定期的に行っている勉強会でReact Native Webのコードを読む機会があったので、共有しようと思います。

実装

思ったよりシンプルでした。
基本的に、変数にHTML tagをstringで持っておいて、それをReact.createElementします

https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/View/index.js

...
const View = () => {
let component = 'div';
...
return createElement(component, props, ...);
}

https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/createElement/index.js

const createElement = (component, props, ... => {
  let accessibilityComponent;
  if (component && component.constructor === String) {
    accessibilityComponent = AccessibilityUtil.propsToAccessibilityComponent(props);
  }
  const Component = accessibilityComponent || component;
  const domProps = createDOMProps(Component, props);

  return React.createElement(Component, domProps, ...children);
};

export default createElement;

View componentにpropsでaccessibilityRoleという値を渡せるのですが、ここで、headingを渡すとViewがh# tagになったり、formを渡すとform tagになってマウントされます。

https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/modules/AccessibilityUtil/propsToAccessibilityComponent.js

const roleComponents = {
  ...
  form: 'form',
  ...
};

...

const propsToAccessibilityComponent = (props) => {
  ...
  const role = propsToAriaRole(props);
  if (role) {
    if (role === 'heading') {
      // accessibilityLevelをprops渡すと、heading tagの数値が決まる。
      const level = props.accessibilityLevel || props['aria-level'];
      if (level != null) {
        return `h${level}`;
      }
      return 'h1';
    }
    return roleComponents[role];
  }
};

export default propsToAccessibilityComponent;

今後

React.createElementしますと言ったもののReact.createElementが何しているかいまいちわからないので、今度はそこの実装を読んでみようと思います

Discussion