# Context Api 範例二:傳token進每一頁,跨元件傳資料 1. 新增context資料夾,裡面放所有context api檔案 ```javascript= import { createContext } from 'react'; export const SendTokenContext = createContext({}); export default SendTokenContext; ``` ![](https://i.imgur.com/Ka3ebLq.png) 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; ```