Listed


React--使用Hook和Context创建全局提示框

做一个全局的提示框,是非常有必要的,在使用的地方直接调用,而非在每个页面都插入一个提示框组件,可以使用这种技术的还有modal、notfication、dialog、spinner。

创建应用 #

环境准备,安装node、npm 或 yarn

1
2
3
npx create-react-app react-alert
cd react-alert
npm start

创建alert #

创建context文件

1
2
mkdir src/context
touch src/context/alert-context.js

创建完成之后的目录

1
2
3
4
src
├ ...
├── context
│   └── alert-context.js

文件创建好了之后,接下来就要往里填充内容,修改alert-context.js, 先导入依赖

1
import React, { useState, createContext, useContext, useEffect } from "react";

创建context对象

1
const AlertContext = createContext();

定义alert组件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const Alert = ({ onClick }) => {
  return (
    <div className="alert-wrapper">
      <div className="alert">
        <div>提示信息</div>
        <button onClick={onClick}>关闭</button>
      </div>
    </div>
  );
};

创建context provider

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
  const AlertProvider = (props) => {
  const [isDisplaying, setIsDisplaying] = useState(false);

  const show = () => setIsDisplaying(true);
  const dismiss = () => setIsDisplaying(false);
  const onClick = () => setIsDisplaying(false);

  return (
    <AlertContext.Provider value={{ show, dismiss }} {...props}>
      {props.children}
      {isDisplaying && <Alert onClick={onClick} />}
    </AlertContext.Provider>
  );
};

AlertProvider创建完成,一般我们会用其包裹应用入口组件,一般是<App /> 。但是,使用前需要导出,现在我们创建一个自定义 hook,将外部使用到的内容导出

1
2
3
4
const useAlert = () => {
  return useContext(AlertContext);
};
export default { AlertContext, useAlert };

使用alert #

下面就是如何使用以上制作的组件,首先配置AlertProvider,修改index.js

1
2
3
4
5
6
7
8
import { AlertProvider } from "./context/alert-context";
// ...
ReactDOM.render(
  <AlertProvider>
    <App />
  </AlertProvider>,
  document.getElementById("root")
);

然后,在需要显示提示框,也就是需要调用show,dismiss的地方引入userAlert,修改App.js,在其中添加一个测试按钮

1
2
3
4
5
6
import { useAlert } from './context/alert-context';
// ...
const alert = useAlert();
const onClick = () => alert.show();
// ...
<button onClick={onClick}>提示</button>;

以上就是基本的创建和使用,接下来可以对alert进行一点改造,使其更加完善

补充,给show添加参数 #

如果想让alert更加灵活,我们需要在show函数添加params 参数,最终将params传入alert,参数内容可以是title、icon等信息,修改alert-context.js

1
2
3
4
5
6
7
8
9
//...
const [params, setParams] = useState();
//...
const show = (params) => {
  params && setParams(params);
  setIsDisplaying(true);
};
// ...
{isDisplaying && <Alert onClick={onClick} {...params} />;}

补充,按ESC键,隐藏提示框 #

使用useEffect, 在组件挂载时绑定ESC键,组件卸载时移除键绑定,在alert组件添加

1
2
3
4
5
6
7
8
9
useEffect(() => {
  const bind = (e) => {
    if (e.keyCode !== 27) return;
    if (document.activeElement && ["INPUT", "SELECT"].includes(document.activeElement.tagName)) return;
    onClick && onClick();
  };
  document.addEventListener("keyup", bind);
  return () => document.removeEventListener("keyup", bind);
}, []);

至此,一个全局的提示框就处理好了,至于样式,每个应用的风格各不相同,可以自由发挥。