Skip to content

Avatar - Expose onError  #5116

@dylan-westbury

Description

@dylan-westbury

Description

Currently for the Avatar component, it is consuming the React Native Image onError method, which prevents an application handling an image loading error.

https://github.com/GeekyAnts/NativeBase/blob/master/src/components/composites/Avatar/Avatar.tsx

Problem Statement

An application may want to handle an error when an image has an error, for example when a presigned url expires the image may stop showing. An application may want to regenerate the url as it has expired to continue showing an image.

Proposed Solution or API

import React, { memo, forwardRef } from 'react';
import { Box, Image } from '../../primitives';
import { usePropsResolution } from '../../../hooks/useThemeProps';
import type { IAvatarProps } from './types';
import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps';
import isNil from 'lodash.isnil';
import has from 'lodash.has';

const Avatar = ({ children, ...props }: IAvatarProps, ref: any) => {
  const [error, setError] = React.useState(false);
  const { _image, _badgeSize, source, onError = () => {}, ...resolvedProps } = usePropsResolution(
    'Avatar',
    props
  );

  let Badge = <></>;
  const remainingChildren: JSX.Element[] = [];
  //  Pop Badge from children
  React.Children.map(children, (child) => {
    if (
      typeof child?.type === 'object' &&
      child?.type.displayName === 'AvatarBadge'
    ) {
      Badge = React.cloneElement(child, { size: _badgeSize[0] });
    } else {
      remainingChildren.push(child);
    }
  });

  //TODO: refactor for responsive prop
  if (useHasResponsiveProps(props)) {
    return null;
  }

  const getSource = () => {
    if (source) {
      if (has(source, 'uri') && !isNil(source.uri)) {
        return source;
      } else if (!has(source, 'uri')) {
        return source;
      }
    }
    return null;
  };

  const imageSource = getSource();

  const onImageError = (err) => {
    setError(true);
    onError(err);
  }

  return (
    <Box {...resolvedProps}>
      {imageSource && !error ? (
        <Image
          source={source}
          onError={onImageError}
          {..._image}
          ref={ref}
        />
      ) : (
        remainingChildren.length !== 0 && remainingChildren
      )}
      {Badge}
    </Box>
  );
};

export default memo(forwardRef(Avatar));

Create method onImageError and continue with same functionality of setState, while calling new Avatar prop onError

Alternatives

No response

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions