# Context Api 範例二:傳token進每一頁,跨元件傳資料
1. 新增context資料夾,裡面放所有context api檔案
```javascript=
import { createContext } from 'react';
export const SendTokenContext = createContext({});
export default SendTokenContext;
```

2. App元件寫法
```javascript=
import React, { useState } from "react";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import { Layout, Spin, Icon } from "antd";
import { SendTokenContext } from "./context/SendTokenContext";
import Login from "./components/Login/Login";
import Top from "./components/Top/Top";
import MainMenu from "./components/MainMenu/MainMenu";
import AnnounceList from "./components/AnnounceList/AnnounceList";
import "./App.css";
const { Header, Sider, Content } = Layout;
// 自定義全局Loading樣式
const selfLoading = <Icon type="loading" style={{ fontSize: 40 }} spin />;
Spin.setDefaultIndicator(selfLoading);
function App() {
const [open, setOpen] = useState(false);
const [isLogin, setIsLogin] = useState(false);
const [token, setToken] = useState("");
const [userID, setUserID] = useState("");
const toggle = () => setOpen(!open);
const SendTokenContextValue = { // 設定context api value,將要傳的東西放在這,可以放state跟function
token,
setToken,
userID,
setUserID
};
return (
<SendTokenContext.Provider value={SendTokenContextValue}> // 用SendTokenContext.Provider包住元件
<BrowserRouter>
<Switch>
<Route
path="/login"
render={() => {
return (
<SendTokenContext.Consumer> // 用SendTokenContext.Consumer包住要接東西的元件
<Login
isLogin={setIsLogin}
token={value.setToken}
userID={value.setUserID}
/>
)}
</SendTokenContext.Consumer>
);
}}
/>
{isLogin ? (
<>
<Route
path="/announcelist"
render={() => {
return (
<SendTokenContext.Consumer>
{value => (
<Layout>
<Sider trigger={null} collapsed={open}>
<MainMenu userID={value.userID} />
</Sider>
<Layout>
<Header className="header">
<Top onClick={toggle} userID={value.userID} />
</Header>
<Content className="content-wrap">
<AnnounceList
token={value.token}
userID={value.userID}
/>
</Content>
</Layout>
</Layout>
)}
</SendTokenContext.Consumer>
);
}}
/>
) : (
<Redirect replace to="/login" />
)}
</Switch>
</BrowserRouter>
</SendTokenContext.Provider>
);
}
export default App;
```
3. MainMenu元件寫法
```javascript=
import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import Version from "../Version/Version";
import { Menu, Icon } from "antd";
import "./MainMenu.css";
class MainMenu extends Component {
render() {
const key = function() {
switch (this.props.match.url) {
case "/announcelist":
return "1";
case "/symbolMapping":
return "2";
case "/symbolPresented":
return "3";
case "/SysSelfName":
return "4";
case "/sysSelfSeleted":
return "5";
case "/accountwhitelist":
return "6";
case "/backstageuser":
return "7";
case "/login":
return "8";
default:
return "0";
}
}.bind(this)();
return (
<Menu selectedKeys={[key]} theme="dark" className="menu">
<Menu.Item key="1">
<Icon type="mail" />
<span>公告管理</span>
<Link to={"/announcelist"} />
</Menu.Item>
<Menu.Item key="2">
<Icon type="appstore" />
<span>對應表</span>
<Link to={"/symbolMapping"} />
</Menu.Item>
<Menu.Item key="3">
<Icon type="plus-circle" />
<span>商品上架維護</span>
<Link to={"/symbolPresented"} />
</Menu.Item>
<Menu.Item key="4">
<Icon type="font-size" />
<span>永豐精選群組名稱設定</span>
<Link to={"/SysSelfName"} />
</Menu.Item>
<Menu.Item key="5">
<Icon type="stock" />
<span>永豐精選</span>
<Link to={"/sysSelfSeleted"} />
</Menu.Item>
<Menu.Item key="6">
<Icon type="user" />
<span>白名單</span>
<Link to={"/accountwhitelist"} />
</Menu.Item>
{this.props.userID === "admin" && ( // 從app來的userID
<Menu.Item key="7">
<Icon type="medium" />
<span>帳號管理</span>
<Link to={"/backstageuser"} />
</Menu.Item>
)}
<Menu.Item key="8">
<Icon type="logout" />
<span>登出</span>
<Link to={"/login"} />
</Menu.Item>
<div className="menu-version">
<Version />
</div>
</Menu>
);
}
}
export default withRouter(MainMenu);
```
4. Login元件寫法
```javascript=
import React from "react";
import Version from "../Version/Version";
import { withRouter } from "react-router-dom";
import { apiUserLogin } from "../../api/api";
import { Form, Icon, Input, Button, message } from "antd";
import icon from "../../static/image/logo.png";
import "./Login.css";
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
userID: "admin",
password: "admin"
};
}
handleSubmit = e => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log("Received values of form: ", values);
}
apiUserLogin({
userID: values.userID,
password: values.password
})
.then(res => {
if (!res.data.result) {
message.error(res.data.reason);
} else {
this.props.isLogin(true);
this.props.token(res.data.token); // 從app來的token
this.props.userID(values.userID); // 從app來的userID
this.props.history.replace("./announcelist", {});
}
})
.catch(err => {
message.error(`網路連線有問題`);
});
});
};
littleBackDoorForDevelop = () => {
this.setState(prevState => {
return {
userID: prevState.userID === "admin" ? "rubio" : "admin",
password: "admin"
};
});
};
render() {
const { getFieldDecorator } = this.props.form;
return (
<>
<Form onSubmit={this.handleSubmit} className="login-form">
<div className="wrap-login">
<div className="logo-wrap" onClick={this.littleBackDoorForDevelop}>
<img src={icon} alt="Icon" className="logo" />
</div>
<span className="logo-title">永豐期貨 - 後台管理</span>
<Form.Item className="Username-input">
{getFieldDecorator("userID", {
rules: [{ required: true, message: "請輸入帳號" }],
initialValue: `${this.state.userID}`
})(
<Input
prefix={
<Icon type="user" style={{ color: "rgba(0,0,0,.25)" }} />
}
placeholder="userID"
/>
)}
</Form.Item>
<Form.Item className="Password-input">
{getFieldDecorator("password", {
rules: [{ required: true, message: "請輸入密碼" }],
initialValue: `${this.state.password}`
})(
<Input.Password
prefix={
<Icon type="lock" style={{ color: "rgba(0,0,0,.25)" }} />
}
type="text"
placeholder="Password"
visibilityToggle
/>
)}
</Form.Item>
<Form.Item className="login-button">
<Button
type="primary"
htmlType="submit"
className="login-form-button"
>
登入
</Button>
</Form.Item>
<div className="logo-version">
<Version />
</div>
</div>
</Form>
</>
);
}
}
const WrapLogin = withRouter(Form.create({ name: "normal_login" })(Login));
export default WrapLogin;
```