需求中常用的npm包

346 阅读2分钟

1.react-copy-to-clipboard

复制到剪贴板 React 组件

截屏2022-06-28 19.48.25.png

npm install --save react-copy-to-clipboard

使用案例:

import React, { useState, useEffect } from 'react';
import {CopyToClipboard} from 'react-copy-to-clipboard';
import { connect } from 'react-redux';

function Family(props) {
  const [count, setCount] = useState(0);
  const [value,setValue] = useState("");
  const [copied,setCopied] = useState(false);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <input value={value} onChange={({target: {value}}) => {
      setValue(value);
      setCopied(false);
      }} />
        <CopyToClipboard text={value}
          onCopy={() => setCopied(true)}>
          <button>复制</button>
        </CopyToClipboard>
        {copied ? <span style={{color: 'red'}}>Copied.</span> : null}
    </div>
  );
}

export default connect(state=>state)(Family)

2.react-json-view

RJV 是一个 React 组件,用于显示和编辑 javascript 数组和 JSON 对象。 该组件提供了一个响应式界面,用于在 Web 浏览器中显示数组或 JSON

截屏2022-06-28 19.49.50.png

npm install --save react-json-view

使用案例:

import React, { useState, useEffect } from 'react';
import ReactJson from 'react-json-view';
import { connect } from 'react-redux';

function Family(props) {
    const [data, setData]= useState<string>(''); // 举例 `{"code":200}


  // JSON格式化
  function stringToJson(_json = '') {
    console.log(_json);
    let json = {'message': '当前json格式错误!'};
    if (_json) {
      try {
        json = JSON.parse(_json);
      } catch (e) {
        console.log('Error', '当前json格式错误!');
      }
    } else {
      json = {'message': ''};
    }
    return json;
  }

  return (
    <>
     <ReactJson style={{width: '100%', height: 'calc(100vh - 370px)', overflow: 'auto'}} src={stringToJson(data)} />
    </>
  );
}

export default connect(state=>state)(Family)

3.react-infinite-scroll-component

只需 4.15 kB 即可消除所有无限滚动问题的组件!添加了下拉刷新功能。一个真正有效的无限滚动,而且集成起来超级简单

截屏2022-06-28 19.47.30.png

  npm install --save react-infinite-scroll-component
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import InfiniteScroll from "react-infinite-scroll-component";

const style = {
  height: 30,
  border: "1px solid green",
  margin: 6,
  padding: 8
};
function Family(props) {
  const [items,setItems] = useState(Array.from({ length: 20 }));
 const fetchMoreData = () => {
    setTimeout(() => {
      setItems(items.concat(Array.from({ length: 20 })));  
    }, 1500);
  };
  return (
    <>
        <h1>demo: react-infinite-scroll-component</h1>
        <hr />
        <InfiniteScroll
          dataLength={items.length}
          next={fetchMoreData}
          hasMore={true}
          loader={<h4>Loading...</h4>}
        >
          {items.map((i, index) => (
            <div style={style} key={index}>
              div - #{index}
            </div>
          ))}
        </InfiniteScroll>
    </>
  );
}

export default connect(state=>state)(Family)

4. react-highlight-words

React 组件以突出显示较大文本正文中的单词。

截屏2022-06-28 19.47.18.png

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import Highlighter from "react-highlight-words";


function Family(props) {
  return (
    <div>
        <Highlighter
    highlightClassName="YourHighlightClass"
    searchWords={["and", "or", "the"]}
    autoEscape={true}
    textToHighlight="The dog is chasing the cat. Or perhaps they're just playing?"
  />
    </div>
  );
}

export default connect(state=>state)(Family)

5.react-axios-http

这是一款结合axios和react的封装请求库, 主要解决了请求调用处理的统一和接口的统一管理, 以及在项目中的接口便捷调用

初始化

// ./http
import http, { combineApi } from "react-axios-http"

const apis = {
  // demo
  get: {
    // get 默认
    url: `/projectManage/show`,
    //余下参数配置支持axios中的参数
  }
  post: {
    // post
    url: `/projectManage/show`,
    method: 'post',
    // isFormData: true 默认false
    // 是否需要以formData形式传参
    // isQuery: true 默认false
    // post请求下,是否以url Query方式 ?pageNum=1&pageSize=10,

    //余下参数配置支持axios中的参数
  },
  put: {
    // put
    url: `/projectManage/show`,
    method: 'put',
    // isFormData: true 默认false
    // 是否需要以formData形式传参
    // isQuery: true 默认false
    // put请求下,是否以url Query方式 ?pageNum=1&pageSize=10

    //余下参数配置支持axios中的参数
  },
  delete: {
    // delete
    url: `/projectManage/show`,
    method: 'delete',

    //余下参数配置支持axios中的参数
  },
  getJsonp: {
    // jsonp
    url: `/projectManage/show`,
    method: 'getJsonp',
  },
};

/* combineApi合并apis,作用域。
const IO = http(combineApi({
  apis_1: apis,
  apis_2: apis,
  apis_3: apis,
},
true/false 默认true,作用域开启
)); */

const IO = http(apis);

// const IO = http(apis, {
//   /* {opt} 默认可不传 */
//   // 高级模式下的数据返回结果处理方式
//   resultMode: 'native',// 可选array, 默认已设置native
//   prefix: '', // 接口统一前缀
//   余下参数配置支持axios中的参数
// });

IO.interceptors.request.use(
  config => {
    console.log(config, 'interceptors request');
    return config;
  },
  error => Promise.reject(error),
);

IO.interceptors.response.use(
  response => {
    console.log(response, 'interceptors response');
    return response;
  },
  error => Promise.reject(error),
);

export default IO;

项目中基本使用方式

// 上面文件
import IO from './http'

const opt = {
  key1: 'value1',
  key2: 'value2',
}

const handler = (res) => {
  // res为返回的结果。
  return res;
}

// IO.getxxx(opt, handler)
// opt是传的参数,不需要传的可不写;
// handler 是对返回结果的二次加工,可不写;

IO.getxxx(opt, handler)
  .then(res => {
    // do something
  });

// 如无参数,直接对返回结果的二次加工
IO.getxxx(handler)
  .then(res => {
    // do something
  });

IO.getxxx().then(res => {
  // do something
});

基本使用说明

  • 默认get请求
  • 导出文件 import IO from './http'
  • 接口请求使用,直接IO.getxxx(),
  • getxxx为apis中一接口名
  • IO.getxxx(opt, handler),()中get和post请求无参数可为(空)
  • handler 是对返回结果的二次加工,可不写;
  • opt 此参数为post和get请求参数,类型皆为对象,如
  • IO.getxxx({
  • key: value,
  • key: value,
  • }, handler)

具体使用请参考 example目录;

高级使用方式

模仿react-redux方式
// 父组件或者根组件
import { ProviderApi } from "react-axios-http";
import apis from './http'
import Child from './Child'

ReactDOM.render(
    <ProviderApi apis={apis}>
        <Child />
    </ProviderApi>)
  document.getElementById("container")
);

//子组件

import React, { Component } from 'react'
import { connectApi } from "react-axios-http";

// 高级处理模式1 resultMode = 'native';默认

// 支持装饰器写法
// 1、@connectApi
// 2、@connectApi('apis_1')
// 3、@connectApi(Child,'apis_1')
class Child extends Component {

  // 使用方式1
  getFetch = async () => {
    const { postxxx } = this.props;
    const res = await postxxx(/*对象参数*/, /* handler 二次加工函数,可不写 */);
    // 如无参数,直接对返回结果的二次加工
    // const res = await postxxx(/* handler 二次加工函数,可不写 */);
    //to do something
  }
  // 使用方式2
  getFetch = () => {
    const { postxxx } = this.props;
    postxxx(/*对象参数*/, /* handler 二次加工函数,可不写 */)
    // 如无参数,直接对返回结果的二次加工
    // postxxx(/* handler 二次加工函数,可不写 */)
    .then(res => {
      //to do something
    });
  }

  render() {
    return (
      <div onClick={this.getFetch}>
      </div>
    )
  }
}

export default connectApi(Child);

// 高级处理模式2 resultMode = 'array,
// 返回一个数组,错误优先处理方式
class Child extends Component {

  // 使用方式1
  getFetch = async () => {
    const { postxxx } = this.props;
    const [err, res] = await postxxx(/*对象参数*/, /* handler 二次加工函数,可不写 */);
    // 如无参数,直接对返回结果的二次加工
    // const [err, res] = await postxxx(/* handler 二次加工函数,可不写 */);
    // err参数不为空则说明请求出现请求异常或者错误
    if (!err) {
      //to do something
    }
  }
  // 使用方式2
  getFetch = () => {
    const { postxxx } = this.props;
    postxxx(/*对象参数*/, /* handler 二次加工函数,可不写 */)
    .then(([err, res]) => {
      if (!err) {
        //to do something
      }
    });
  }

  render() {
    return (
      <div onClick={this.getFetch}>
      </div>
    )
  }
}

export default connectApi(Child);

6.react-hot-loader

将应用程序标记为可热重载。 (更喜欢使用热助手,请参阅下面的迁移详细信息)。 这种低级方法可以让您制作 hot imports__,而不是导出。

import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import App from './containers/App';
 
const render = Component => {
  ReactDOM.render(
    <AppContainer>
      <Component />
    </AppContainer>,
    document.getElementById('root'),
  );
};
 
render(App);
// webpack Hot Module Replacement API
if (module.hot) {
  // keep in mind - here you are configuring HMR to accept CHILDREN MODULE
  // while `hot` would configure HMR for the CURRENT module
  module.hot.accept('./containers/App'() => {
    // if you are using harmony modules ({modules:false})
    render(App);
    // in all other cases - re-require App manually
    render(require('./containers/App'));
  });
}

7.react-hotkeys-hook

用于在组件中使用键盘快捷键的 React 钩子

npm i react-hotkeys-hook

截屏2022-07-01 16.35.59.png

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { useHotkeys } from 'react-hotkeys-hook';


function Family(props) {
  const [count, setCount] = useState(0);

  useHotkeys('ctrl+k', () => setCount(prevCount => prevCount + 1))

  return (
    <>
       <p>You clicked {count} times</p>
    </>
  );
}

export default connect(state=>state)(Family)

8.react-lazyload

延迟加载您的组件、图像或任何对性能很重要的东西

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import LazyLoad from 'react-lazyload';
import imageUrl from '../../assets/images/1.png';

function Family(props) {
  return (
    <>
       <LazyLoad  once height={200} offset={100}>
        <img src={imageUrl}  alt="" width="200" height="200"/> 
      </LazyLoad>
    </>
  );
}

export default connect(state=>state)(Family)

9.react-markdown

这个包是一个 React 组件,可以给它一个 markdown 字符串,它将安全地呈现给 React 元素。你可以传递插件来改变 markdown 转换为 React 元素的方式,并传递将被使用的组件而不是普通的 HTML 元素

10.react-syntax-highlighter

React 的语法高亮组件

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import ReactMarkdown from 'react-markdown'
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'
import {dark} from 'react-syntax-highlighter/dist/esm/styles/prism'

const markdown = `Here is some JavaScript code:

~~~js
console.log('It works!')
~~~
`
function Family(props) {
  return (
    <>
       <ReactMarkdown
        children={markdown}
        components={{
          code({node, inline, className, children, ...props}) {
            const match = /language-(\w+)/.exec(className || '')
            return !inline && match ? (
              <SyntaxHighlighter
                children={String(children).replace(/\n$/, '')}
                style={dark}
                language={match[1]}
                PreTag="div"
                {...props}
              />
            ) : (
              <code className={className} {...props}>
                {children}
              </code>
            )
          }
        }}
  />
    </>
  );
}

export default connect(state=>state)(Family)

11.react-window

用于高效渲染大型列表和表格数据的 React 组件 更多

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { FixedSizeList as List } from "react-window";

import AutoSizer from "react-virtualized-auto-sizer";

const Row = ({ index, style }) => (

<div className={index % 2 ? "ListItemOdd" : "ListItemEven"} style={style}>
Row {index}
</div>
);
`
function Family(props) {
  return (
    <>
     <AutoSizer>
        {({ height, width }) => (
        <List
        className="List"
        height={height}
        itemCount={1000}
        itemSize={35}
        width={width}>
        {Row}
        </List>
        )}
        </AutoSizer>
    </>
  );
}

export default connect(state=>state)(Family)

12.react-beautiful-dnd

使用 React 对列表进行漂亮且易于访问的拖放操作

import React, { Component } from "react";

import ReactDOM from "react-dom";

import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";


// fake data generator

const getItems = count =>

Array.from({ length: count }, (v, k) => k).map(k => ({

id: `item-${k}`,

content: `item ${k}`

}));



// a little function to help us with reordering the result

const reorder = (list, startIndex, endIndex) => {

const result = Array.from(list);

const [removed] = result.splice(startIndex, 1);

result.splice(endIndex, 0, removed);


return result;

};



const grid = 8;



const getItemStyle = (isDragging, draggableStyle) => ({

// some basic styles to make the items look a bit nicer

userSelect: "none",

padding: grid * 2,

margin: `0 0 ${grid}px 0`,


// change background colour if dragging

background: isDragging ? "lightgreen" : "grey",



// styles we need to apply on draggables

...draggableStyle

});



const getListStyle = isDraggingOver => ({

background: isDraggingOver ? "lightblue" : "lightgrey",

padding: grid,

width: 250

});



class App extends Component {

constructor(props) {

super(props);

this.state = {

items: getItems(10)

};

this.onDragEnd = this.onDragEnd.bind(this);

}



onDragEnd(result) {

// dropped outside the list

if (!result.destination) {

return;

}



const items = reorder(

this.state.items,

result.source.index,

result.destination.index

);



this.setState({

items

});

}



// Normally you would want to split things out into separate components.

// But in this example everything is just done in one place for simplicity

render() {

return (

<DragDropContext onDragEnd={this.onDragEnd}>

<Droppable droppableId="droppable">

{(provided, snapshot) => (

<div

{...provided.droppableProps}

ref={provided.innerRef}

style={getListStyle(snapshot.isDraggingOver)}

>

{this.state.items.map((item, index) => (

<Draggable key={item.id} draggableId={item.id} index={index}>

{(provided, snapshot) => (

<div

ref={provided.innerRef}

{...provided.draggableProps}

{...provided.dragHandleProps}

style={getItemStyle(

snapshot.isDragging,

provided.draggableProps.style

)}

>

{item.content}

</div>

)}

</Draggable>

))}

{provided.placeholder}

</div>

)}

</Droppable>

</DragDropContext>

);

}

}



// Put the thing into the DOM!

ReactDOM.render(<App />, document.getElementById("root"));

13.react-beforeunload

侦听 beforeunload 窗口事件的 React 组件和钩子。

import { Beforeunload } from 'react-beforeunload';

class Example extends React.Component {
  state = { value: '' };

  render() {
    return (
      <>
        {this.state.value !== '' && (
          <Beforeunload onBeforeunload={(event) => event.preventDefault()} />
        )}
        <input
          onChange={(event) => this.setState({ value: event.target.value })}
          value={this.state.value}
        />
      </>
    );
  }
}

14.react-cookie

React 的通用 cookie

// Root.jsx
import React from 'react';
import App from './App';
import { CookiesProvider } from 'react-cookie';

export default function Root() {
  return (
    <CookiesProvider>
      <App />
    </CookiesProvider>
  );
}

// App.jsx
import React from 'react';
import { useCookies } from 'react-cookie';

import NameForm from './NameForm';

function App() {
  const [cookies, setCookie] = useCookies(['name']);

  function onChange(newName) {
    setCookie('name', newName, { path: '/' });
  }

  return (
    <div>
      <NameForm name={cookies.name} onChange={onChange} />
      {cookies.name && <h1>Hello {cookies.name}!</h1>}
    </div>
  );
}

export default App;

15.react-split-pane-next

Split-Pane React 组件,可以垂直或水平嵌套或拆分

import SplitPane, { Pane } from 'react-split-pane-next';

<SplitPane split="vertical">
  <Pane initialSize="200px">You can use a Pane component</Pane>
  <div>or you can use a plain old div</div>
  <Pane initialSize="25%" minSize="10%" maxSize="500px">
    Using a Pane allows you to specify any constraints directly
  </Pane>
</SplitPane>;

16.video-react

Video.React 是一个使用 React 库从头开始为 HTML5 世界构建的网络视频播放器。


import React from 'react';
import { Player } from 'video-react';

export default props => {
  return (
    <Player>
      <source src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4" />
    </Player>
  );
};