如何在 Reason 中使用 useContext Hook 创建音乐播放器(第一部分)
我们正在建造什么?
更新:
ReasonML + BuckleScript 现已合并为 Rescript。
由于这些工具的生态系统发生了变化,本文内容不再准确。
我们正在建造什么?
本教程将向您展示如何使用ReasonReact和hooks构建一个音乐播放器useContext。
您将学习如何启动一个 ReasonReact 项目,如何构建一个简单的应用程序,以及如何将 hooks 与 ReasonReact 结合使用。
为什么选择 ReasonML 和 ReasonReact?
ReasonReact提供了一种类型安全的方式来构建 React 应用。它利用了成熟的 OCaml 语言,该语言拥有卓越的类型系统。此外,它还提供了速度极快的编译器和出色的面向 JavaScript 的工具。
免责声明:我本人也是 ReasonReact 的初学者,因此无法保证本教程完全遵循最佳实践。
本系列博客文章改编自 James King 撰写的优秀文章《如何在 React 中使用 useContext Hook》 。
本教程假定读者已具备 React 的基本知识。ReasonReact 的底层正是 React。
你可以在GitHub上找到所有代码。
这是什么useContext?
来自React 文档:
Context 旨在共享 React 组件树中可视为“全局”的数据,例如当前已验证用户、主题或首选语言。
我们将构建一个自定义MusicPlayer组件和一个useMusicPlayer钩子,使我们的应用程序能够访问一个简单的 mp3 HTML 音频播放器。
项目启动
ReasonML 是 OCaml 的一种语法和工具链,我们需要安装一些 npm 包才能使用它。您需要Node.js和npm(或 yarn)。
安装
npm install -g bs-platform --unsafe-perm
(我使用pnpm安装本地软件包,所以你会在仓库pnpm-lock.yml中找到一个文件。)
我们需要 BuckleScript 将 ReasonML 编译成 JavaScript。
关于编辑器支持,请查看Reason 文档。
关于 Vim,您可以查看我关于使用 Vim 进行 ReasonML 开发的博客文章。
创建 ReasonReact 项目
在您的终端中:
bsb -init reason-music-player -theme react-hooks
cd reason-music-player && npm install
这些命令会创建一个样板项目,我们需要根据自己的需要进行配置。
请注意:样板代码已更改。我会帮助您使用webpack
设置项目。但有了新的配置,这不再是绝对必要的。 如果您不想使用 webpack,可以使用新的默认样板代码,具体说明请参见[此处] 。README
首先,bsconfig.json该文件告诉BuckleScript如何处理编译成 JavaScript 的过程:
{
"name": "reason-music-player",
"reason": {
"react-jsx": 3
},
"sources": {
"dir": "src",
"subdirs": true
},
"package-specs": [
{
"module": "es6", // *new*: use ES6 imports
"in-source": true
}
],
"suffix": ".bs.js",
"namespace": true,
"bs-dependencies": ["reason-react"],
"refmt": 3
}
我们的package.json界面对于 JavaScript 开发者来说应该很熟悉。我们将同时安装webpack 和 Bucklescript,以便它们能够一起运行:
npm i --save-dev concurrently
调整脚本部分package.json:
scripts": {
"start": "concurrently -k \"npm run start:bsb\" \"npm run start:webpack\"",
"start:bsb": "bsb -clean-world -make-world -w",
"start:webpack": "webpack-dev-server --port 3000",
"build": "npm run build:webpack",
"build:webpack": "NODE_ENV=production webpack",
"format": "refmt src/*.re"
},
我们还需要一个webpack的配置文件:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const outputDir = path.join(__dirname, 'build/')
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
entry: './src/Index.bs.js',
mode: isProd ? 'production' : 'development',
output: {
path: outputDir,
filename: 'Index.js',
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
favicon: './src/favicon.ico',
inject: false,
}),
],
devServer: {
compress: true,
contentBase: outputDir,
port: process.env.PORT || 8000,
historyApiFallback: true,
},
}
现在我们可以在终端运行该项目,并在以下位置查看结果https://localhost:3000:
npm run start
示例项目包含示例组件,我们将删除这些组件。只保留src/Index.re.
打开index.html文件并替换内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/fontawesome.min.css"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/solid.min.css"
/>
<title>Reason Music Player</title>
</head>
<body>
<div id="root"></div>
<script src="Index.js"></script>
</body>
</html>
现在我们也可以使用Bulma CSS和Font Awesome 图标了。
我们还会修改src/Index.re:
ReactDOMRe.renderToElementWithId(<App />, "root");
我们的索引组件现在会将id 为“root”App的组件渲染到 HTML 中div。我们会看到一个错误,因为该App组件尚不存在。
让我们一起创造它:src/App.re
[@react.component]
let make = () => <div />
这个语法看起来有点奇怪。每个 ReasonReact 组件都有一个make函数,用于创建一个 React 元素。ReasonReact底层
使用了函数式组件和React Hooks 。更多详情
请查看ReasonReact 文档。
我们将创建一个辅助函数来渲染 JSX 中的字符串:src/ReactUtils.re
external s: string => React.element = "%identity";
(更多信息请查看 Florian Hammerschmidt 在 dev.to 上的帖子。)
现在,让我们更新一下App组件:
open ReactUtils; // (A)
[@react.component]
let make = () =>
<div className="section is-fullheignt">
<div className="container">
<div className="column is-6 is-offset-4">
<h1 className="is-size-2 has-text-centered">
{s("Reason Music Player")} // (A)
</h1>
<br />
</div>
</div>
</div>;
我们导入了实用模块,现在可以渲染字符串了(参见A)。Reason 是类型安全的,所以你需要告诉程序你想在 JSX 中传递一个字符串。`s`是
BulmaclassName的样式设置方式。
概要
我们安装了 Reason 和 BuckleScript,并为我们的项目搭建了最基本的配置。
ReasonReact 和 BuckleScript 为 JavaScript 开发者提供了熟悉的工具体验。但我们已经发现 ReasonML 和 JavaScript 之间存在一些差异(例如语法、显式渲染字符串)。
延伸阅读
- 如何在 React 中使用 useContext Hook(作者:James King)
- 理性反应
- Reason(React)最佳实践 - 第一部分