npx create-react-app react-travel --template typescript
cd react-travel
npm run start
安装插件:yarn add typescript-plugin-css-modules --save-dev
tsconfig.json中配置插件:"compilerOptions":{ "plugins": [ { "name": "typescript-plugin-css-modules" } ] }
vscode配置:创建.vscode/settings.json
:
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
将App.css重命名为:App.module.css
/* App.module.css */
.center {
text-align: center;
}
.list {
line-height: 30px;
font-size: 20px;
}
定义声明文件custom.d.ts: 对css引用对象的支持,否则.tsx会报错
// custom.d.ts
declare module '*.css' {
const css: { [key: string]: sting };
export default css;
}
组件中使用:
// App.tsx
import styles from './App.module.css';
function App() {
return (
<div className={styles.center}>
<div className={styles.list}>
CSS in JS
</div >
</div>
);
}
export default App;
官网:https://ant.design/index-cn
安装UI组件库:yarn add antd
安装Icon图标:yarn add @ant-design/icons --save
在index.tsx
中引入css:import 'antd/dist/antd.css';
组件中使用UI:
import { Input } from 'antd';
<Input.Search placeholder='请输入关键字' />
组件中使用Icon:
import { MessageOutlined } from '@ant-design/icons';
<MessageOutlined style={{ fontSize: '16px', color: '#08c' }} />;
yarn add react-router-dom --save-dev
react-router
核心框架npm install @types/react-router-dom --save-dev
基础路由eg:
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import { Home } from './pages'
function App() {
return (
<div>
<BrowserRouter>
{/* Switch 解决页面叠加问题,每次只渲染一个路由页面 */}
<Switch>
<Route path="/" component={Home} exact />
<Route path="/signIn" render={(() => <h1>登录页面</h1>)} />
<Route render={(() => <h1>404 not found 页面</h1>)} />
</Switch>
</BrowserRouter>
</div >
);
}
export default App;
使用分段路由Segments:http://localhost:3000/products/11121314
App.tsx
中添加详情页的路由import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import { Home, Detail } from './pages'
function App() {
return (
<div className={styles.App}>
<BrowserRouter>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/detail/:id" component={Detail} /> {/* 路由添加参数id */}
</Switch>
</BrowserRouter>
</div >
);
}
export default App;
Home.tsx
中跳转到详情页的路由使用高阶函数:
import React from "react";
import { withRouter } from "react-router-dom"; // 高阶函数
const HomeComponent: React.FC = ({ history, location, match }) => {
console.log(history, location, match);
return (
<div onClick={() => history.push(`detail/123456`)}>
跳转至详情页,并传递参数id
</div>
);
}
export const Home = withRouter(HomeComponent); // 使用高阶函数封装路由
使用hook:
import React from 'react';
import { useHistory, useLocation, useParams, useRouteMatch } from 'react-router-dom'; // hook
export const Home: React.FC = () => {
// 使用hook
const history = useHistory();
const location = useLocation();
const params = useParams();
const match = useRouteMatch();
return (
<div onClick={() => history.push(`detail/123456`)}>
跳转至详情页,并传递参数id
</div>
);
};
使用Link:
import React from "react";
import { Link } from "react-router-dom"; // link
export const Home: React.FC = () => {
return (
<Link to={`detail/123456`}>
跳转至详情页,并传递参数id
</Link>
);
}
Detail.tsx
详情页中获取参数import React from 'react';
export const Detail: React.FC<any> = (props) => {
console.log(props.match.params.id);
}
npm install react-i18next i18next --save
或
yarn add react-i18next i18next --save
新建文件夹i18n\config.ts
:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import translation_en from './en.json'; // 配置的英文json
import translation_zh from './zh.json'; // 配置的中文json
const resources = {
en: {
translation: translation_en,
},
zh: {
translation: translation_zh,
},
};
i18n.use(initReactI18next).init({
resources,
lng: 'zh',
interpolation: {
escapeValue: false,
},
});
export default i18n;
index.tsx
中引入:import './i18n/config'
组件中Home.tsx
:
import React from 'react';
import { useTranslation } from 'react-i18next'
export const Home: React.FC = () => {
const { t } = useTranslation()
return (
<div>
{t('home.detail')}
</div>
);
};
点击按钮切换,reducer.ts
中:
import i18n from 'i18next';
export interface languageState {
language: 'zh' | 'en';
languageList: { name: string; code: string }[];
}
const defaultState: languageState = {
language: 'zh',
languageList: [
{ name: '中文', code: 'zh' },
{ name: 'English', code: 'en' },
],
};
const reducer = (state = defaultState, action) => {
switch (action.type) {
case 'change_language':
i18n.changeLanguage(action.value);
return { ...state, language: action.value };
default:
return state;
}
};
export default reducer;
React的核心思想就是组件化,组件化带来最大好处就是组件彼此独立,可以复用。
useState
,useEffect
,useContext
,useReducer
use
前缀命名:useXxx
纯函数:给一个函数同样的参数,那么这个函数永远返回同样的值。
副作用与穿函数相反,指一个函数处理了与返回值无关的事情。 输入参数一样,而输出结果不确定的情况就是副作用。 纯函数中没有副作用,有副作用的不是纯函数。
React中的副作用有:state状态的改变、生命周期、构建函数...
函数式组件中使用useEffect
处理副作用
当useEffect
的第二个参数为一个非空数组时,会在count
值发生变化时调用(相当于vue中的watch
)
useEffect(() => {
document.title = `You clicked ${count} times`; // 监听count值变化
}, [count])
当useEffect
的第二个参数为一个空数组时,初始化调用一次之后不再执行(相当于componentDidMount
)
useEffect(() => {
console.log('hello world'); // 仅在初始化时调用一次
}, [])
// 等价于
componentDidMount() {
console.log('hello world');
}
当useEffect
没有第二个参数时,组件的初始化和更新都会执行,(相当于componentDidMount
+ componentDidUpdate
),容易死循环(夺命连环call)
useEffect(() => {
document.title = `You clicked ${count} times`;
});
// 等价于
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
当useEffect
返回一个函数时,这个函数会在组件卸载时执行(相当于componentDidMount
+componentWillUnmount
)
useEffect(() => {
const id = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(id); // 相当于componentWillUnmount
}, []);
// 等价于
componentDidMount() {
this.id = setInterval(() => {
this.setState({count: this.state.count + 1})
}, 1000);
}
componentWillUnmount() {
clearInterval(this.id);
}
简而言之,高阶组件是参数为组件,返回值为新组件的函数。
const hoc = higherOrde(wrappedComponent)
组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。
import React from 'react';
const withAddToCart = (ChildComponent)=>{
return (props) =>{
return <ChildComponent {...props}>
}
}
npm install react-redux @types/react-redux yarn add react-redux @types/react-redux
在index.tsx
中引入Provider:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux'; // 引入Provider
import store from './redux/store'; // 引入store
ReactDOM.render(
<React.StrictMode>
{/* 使用Provider并加载数据仓库 */}
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
组件中使用connect().
import { connect } from 'react-redux';
// ...
export const Xxx = connect(mapStateToProps, mapDispatchToProps)(XxxComponents);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。