---
# System prepended metadata

title: 在 ASP.NET MVC 專案中新增一個 React 元件
tags: [React]

---

---
robots: noindex, nofollow
tags: React
---

# 在 ASP.NET MVC 專案中新增一個 React 元件

接下來我們會示範怎麼在現有的 ASP.NET MVC 專案中，新增一個元件。

## 準備

先啟動 Storybook ，並在 `Frontend/src/stories/` 資料夾新增一個和新元件相關的 `.stories.tsx` 檔，例如：

```typescript=
import React from 'react';
// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
import { Story, Meta } from '@storybook/react/types-6-0';

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

export default {
  title: 'CRM/SettingBlock',
  component: SettingBlock,
  argTypes: {},
} as Meta;

const Template: Story = (args) => <SettingBlock {...args} />;

export const Default = Template.bind({});
```

一開始我們從簡就好，想知道怎麼寫 Storybook Controls ，可以看看[官方教學頁面][storybook-controls]。

同時在 `Frontend/src/components/` 內，新增對應的 `.tsx` 檔：

```typescript=
// SettingBlock.tsx
import styled from 'styled-components';

export const SettingBlock = () => {
  return (
    <div>新元件</div>
  );
};
```

接著切回 `Frontend/` 、啟動 Storybook ，看看元件有沒有出現在左方選單：

```shell=
yarn storybook
```

## 實作

填上元件的肉：

```typescript=
import styled from 'styled-components';
import urlComputerIcon from 'images/Computer-icon.png';

const Outer = styled.div`
  float: left;
  box-sizing: border-box;
`;

const Block = styled.div`
  position: relative;
  padding: 0 0 0 52px;
  box-sizing: border-box;
  padding-bottom: 20px;
  height: 160px;
  padding-right: 15px;
  img {
    position: absolute;
    top: -5px;
    left: 10px;
  }
`;

const Header = styled.div`
  font-size: 100%;
  line-height: 150%;
`;

const Title = styled.span`
  font-size: 18px;
  display: inline-block;
  width: 100%;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
`;

const MenuItem = styled.li`
  display: inline-block;
  font-size: 14px;
  line-height: 18px;
`;

const Menu = styled.ul`
  list-style: none;
  border: 0;
  padding: 0;
  margin: 2px;
  ${MenuItem} + ${MenuItem}:before {
    content: "\\a0|\\a0";
  }
`;

const Link = styled.a`
  color: #92250a;
  text-decoration: none;
`;

export const SettingBlock = () => {
  return (
    <Outer>
      <Block>
        <Header>
          <img src={urlComputerIcon} />
          <Title>系統</Title>
        </Header>
        <Menu>
          <MenuItem>
            <Link href="#">服務資訊</Link>
          </MenuItem>
          <MenuItem>
            <Link href="#">系統設定</Link>
          </MenuItem>
          <MenuItem>
            <Link href="#">佈告欄</Link>
          </MenuItem>
          <MenuItem>
            <Link href="#">事件檢視</Link>
          </MenuItem>
          <MenuItem>
            <Link href="#">刪除過時資料</Link>
          </MenuItem>
          <MenuItem>
            <Link href="#">清除資料</Link>
          </MenuItem>
        </Menu>
      </Block>
    </Outer>
  );
};
```

看看 Storybook 有沒有自動更新畫面，反映您的修改。

## 整合

找到 `Frontend/src/index.ts` ，手動暴露新元件到 `global` 下，讓 ReactJS.NET 找得到它：

```typescript=
import { SettingBlock } from './components';

// 可能的話，只讓 `any` 出現在這個檔案中
(global as any).SettingBlock = SettingBlock;
```

跑前端開發 script ：


```shell=
yarn start
```

它會跑 `webpack --config ./webpack.config.js --watch` ，把打包後的 `*.bundle.js` 放到事先設定好的資料夾中，並監測檔案變化。

打開 Visual Studio ，開啟專案，選擇 `Debug > Debug` ，待瀏覽器開啟後，到已經設定好 ReactJS.NET 的頁面，開啟 devtools ，輸入：

```javascript=
window.SettingBlock;
```

如果看到：

```javascript=
f SettingBlock() {
  return /*#__PURE__*/React.createElement( // 後略...
```

表示該元件已經成功暴露出來。

接著打開對應的 `.cshtml` ，在想要繪製該 React 元件的地方，寫下：

```csharp=
@Html.React("SettingBlock", new {})
```

如果有從 view model 暴露出一些資料，則寫成：

```csharp=
@Html.React("SettingBlock", new { someProp = Model.someProp })
```

最後重新整理頁面，順利的話，就會看到新元件繪製在畫面上。

## 檢查

在 React 或其他前端 library/framework 文章中，會把 server-side rendering React component 這件事情稱為 dehydrate （脫水）。

除了讓搜尋引擎改善 SEO 外，也能讓禁用 JavaScript 的瀏覽器，至少還能看到該元件第一次繪製出來的樣子。

並把讓這些 DOM element 靠 js 動起來這件事，稱為 hydrate （注水）。

接下來我們要檢查看看這段有沒有成功接起來。

對瀏覽器頁面按右鍵，選擇 `檢視網頁原始碼` ，來看看沒有被 js 修改過的 HTML ，順利的話，會在 `<head>` 或 `<body>` 裡看到：

```html=
<style data-styled="true" data-styled-versions="5.1.1">
  /* 一大堆 CSS */
</style>
```

表示成功生成了 styled-components 樣式。

並在想繪製 React 元件的地方，看到：

```html=
<div id="react_0HM6VG98HBCF2"<div class="sc_AxjAm kNmqRE">
  <!-- 元件內容 -->
</div>
```

表示成功 SSR 了 React 元件。

最後操作一下該元件，來確定 React 有沒有成功把 JavaScript 和這些 DOM element 連接起來。

## 發佈

如果 repo 決定將 bundle （打包）好的 js 納入版控，那最後還得在 `Frontend/` 下執行：

```shell=
yarn build
```

來生成 `*.bundle.js` 至對應的目錄下。

否則讓 CI/CD 來做這件事即可。

[storybook-controls]: https://storybook.js.org/docs/react/essentials/controls