React Native实现Toast轻提示和loading

React Native 封装Toast

前言

使用react native的小伙伴都知道,官方并未提供轻提示组件,只提供了ToastAndroid API,顾名思义,只能再安卓环境下使用,对于ios就爱莫能助,故此,只能通过官方的核心组件,自行封装,实现Toast功能

实现

创建文件

首先我们需要创建一个Toast组件,引入对应需要的依赖,icon等等
声明数据类型,通用方法

import React,{Component} from 'react';
import {View,Text,StyleSheet,Animated,Easing} from 'react-native';
import icon_success from '../assets/images/icon-success.png';
import icon_error from '../assets/images/icon-error.png';
import icon_loading from '../assets/images/icon-loading.png';
import icon_warning from '../assets/images/icon-warning.png';

type statetype = {
  isVisible: boolean;
  icon: any;
  message: string;
};

type ParamsType = string | {message: string; duration?: number};
function getParams(data: ParamsType): {message: string; duration: number} {
  let msg!: string;
  let dur!: number;
  if (typeof data === 'string') {
    msg = data;
    dur = 2000;
  } else {
    msg = data.message;
    dur = data.duration != null ? data.duration : 2000;
  }
  return {
    message: msg,duration: dur,};
}

实现样式和UI层次渲染

我们需要创建一个class,接收参数,并根据不同的条件渲染:success、error、warning、show、loading等
并抛出自己的实例

class ToastComponent extends Component<{} | Readonly<{}>,statetype> {
  timeout!: NodeJS.Timeout;
  rotate: Animated.Value = new Animated.Value(0);
  constructor(props: {} | Readonly<{}>) {
    super(props);
    this.state = {
      isVisible: false,icon: null,message: '',};
    Toast.setToastInstance(this);
  }
  showToast(icon: any,message: string,duration: number) {
    this.setState({
      isVisible: true,icon,message,});
    if (duration !== 0) {
      const timeout = setTimeout(() => {
        this.closeToast();
      },duration);
      this.timeout = timeout;
    }
  }
  showRotate() {
    Animated.loop(
      Animated.timing(this.rotate,{
        toValue: 360,duration: 1000,easing: Easing.linear,useNativeDriver: true,}),).start();
  }
  closeToast() {
    this.setState({
      isVisible: false,});
    if (this.timeout) {
      clearTimeout(this.timeout);
    }
  }

  render() {
    const {isVisible,message} = this.state;
    return isVisible ? (
      <View style={style.root}>
        <View style={[style.main,icon === null ? null : style.mainShowStyle]}>
          {icon && (
            <Animated.Image
              style={[
                style.icon,{
                  transform: [
                    {
                      rotate: this.rotate.interpolate({
                        inputRange: [0,360],outputRange: ['0deg','360deg'],},],]}
              source={icon}
            />
          )}
          <Text style={style.tip}>{message}</Text>
        </View>
      </View>
    ) : null;
  }
}

const style = StyleSheet.create({
  root: {
    height: '100%',backgroundColor: 'transparent',position: 'absolute',top: 0,left: 0,right: 0,bottom: 0,zIndex: 99999,alignItems: 'center',justifyContent: 'center',main: {
    maxWidth: 200,maxHeight: 200,backgroundColor: '#00000099',borderRadius: 8,padding: 20,mainShowStyle: {
    minWidth: 140,minHeight: 140,icon: {
    width: 36,height: 36,resizeMode: 'cover',marginBottom: 20,tip: {
    fontSize: 14,color: '#fff',fontWeight: 'bold',textAlign: 'center',});

抛出对外调用的方法

此时我们需要再声明一个class,对外抛出方法以供调用
最后导出即可

class Toast extends Component<{} | Readonly<{}>,{} | Readonly<{}>> {
  static toastInstance: ToastComponent;
  static show(data: ParamsType) {
    const {message,duration} = getParams(data);
    this.toastInstance.showToast(null,duration);
  }
  static loading(data: ParamsType) {
    const {message,duration} = getParams(data);
    this.toastInstance.showToast(icon_loading,duration);
    this.toastInstance.showRotate();
  }
  static success(data: ParamsType) {
    const {message,duration} = getParams(data);
    this.toastInstance.showToast(icon_success,duration);
  }
  static error(data: ParamsType) {
    const {message,duration} = getParams(data);
    this.toastInstance.showToast(icon_error,duration);
  }
  static warning(data: ParamsType) {
    const {message,duration} = getParams(data);
    this.toastInstance.showToast(icon_warning,duration);
  }
  static clear() {
    if (this.toastInstance) {
      this.toastInstance.closeToast();
    }
  }
  static setToastInstance(toastInstance: ToastComponent) {
    this.toastInstance = toastInstance;
  }
  render() {
    return null;
  }
};

export {Toast,ToastComponent};

组件挂载

我们需要将UI层组件在入口TSX文件进行挂载,不然Toast无法渲染

/* APP.tsx */
import React from 'react';
import {StatusBar} from 'react-native';
import {SafeAreaProvider} from 'react-native-safe-area-context';

import {ToastComponent} from './src/components/Toast';

const Stack = createStackNavigator();

function App(): JSX.Element {
  return (
    <SafeAreaProvider>
      <StatusBar barStyle="dark-content" backgroundColor="#EAF7FF" />
      <ToastComponent />
    </SafeAreaProvider>
  );
}

export default App;

API调用

挂载完成,接下来,在我们需要用到的地方,调用即可

import {Toast} from '../../components/Toast';

// 
Toast.success('登录成功');
Toast.error('密码错误');
Toast.warning('我是警告');
Toast.loading('加载中,请稍后');
Toast.loading({message: "我是不关闭的Toast",duration: 0})
Toast.success({message: "我是2秒后关闭的Toast",duration: 2000});
Toast.clear(); // 手动关闭

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件举报,一经查实,本站将立刻删除。

本文链接:https://www.f2er.com/3188638.html

大家都在看

  • 飞码LowCode前端技术系列:如何便捷快速验证实现投产及飞码探索

    本篇文章从数据中心,事件中心如何协议工作、不依赖环境对vue2.x、vue3.x都可以支持、投产页面问题定位三个方面进行分析。
    2023-11-16 博文
  • 如何优雅使用 vuex

    大纲 本文内容更多的是讲讲使用 vuex 的一些心得想法,所以大概会讲述下面这些点: Q1:我为什么会想使用 vuex 来管理数据状态交互? Q2:使用 vuex 框架有哪些缺点或者说副作用? Q3:我是如何在项目里使用 vuex 的? 初识 vuex 对于 vuex,有人喜欢,有人反感 喜欢的人觉
    2023-11-16 博文
  • 第三方组件及计算属性传参的问题解决方式

    1. 前言 唉,好想玩滋嘣。 2. 计算属性直接传参接收不到 表格数据某一列需要用的计算属性时,模板中使用计算属性 fullName 就会直接调用 fullName 函数,而在模板中 fullName(item) 相当于fullName()(item),此处为函数柯里化。 &lt;el-table-
    2023-11-16 博文
  • 记录--Vue3基于Grid布局简单实现一个瀑布流组件

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 在学习Grid布局之时,我发现其是CSS中的一种强大的布局方案,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,在刷某书和某宝首页时,我们发现其展示方式就是一种瀑布流,是一种流行的网站页面布局,视觉表……
    2023-11-16 博文
  • 用强数据类型保护你的表单数据-基于antd表单的类型约束

    接口数据类型与表单提交数据类型,在大多数情况下,大部分属性的类型是相同的,但很少能做到完全统一。我在之前的工作中经常为了方便,直接将接口数据类型复用为表单内数据类型,在遇到属性类型不一致的情况时会使用any强制忽略类型错误。后来经过自省与思考,这种工作模式会引起各种隐藏bug,一定有更……
    2023-11-16 博文
  • pinia的使用

    前言 最近新开了个项目,以前老项目都是vue2+vuex开发的,都说用vue3+pinia爽得多,那新项目就vue3+pinia吧。这里记录一下pinia的使用。 使用方法 安装pinia: npm i pinia main.js中引入pinia: //main.js import { create
    2023-11-16 博文
  • 记录--让我们来深入了解一下前端“三清”是什么

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前端“三清” 在前端开发中,我们经常听到关于“三清”的说法,即 window、document、Object。这三者分别代表了 BOM(浏览器对象模型)、DOM(文档对象模型)以及 JS 的顶层对象。在这个体系中,我们通过 JavaScr
    2023-11-16 博文
  • 记录--啊?Vue是有三种路由模式的?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 众所周知,vue路由模式常见的有 history 和 hash 模式,但其实还有一种方式-abstract模式(了解一哈~) 别急,本文我们将重点逐步了解: 路由 + 几种路由模式 + 使用场景 + 思考 + freestyle 路由概念
    2023-11-16 博文