美文网首页
2023-04-21 react hook从0搭建项目及开发总结

2023-04-21 react hook从0搭建项目及开发总结

作者: 换昵称了 | 来源:发表于2023-04-23 11:41 被阅读0次

使用create-react-app搭建项目,默认隐藏webpack文件,引入less需要把配置文件暴露出来,操作如下:
npm run eject

注:此操作不可逆,一旦暴露不可回退。

1.wepack 配置了less(webpck版本:^5.64.4)

npm install less less-loader --save-dev
在webpack.config.js文件头部定义less正则:

const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
const lessGlobalUrl = "./../src/*****.less";

查找module,在module.rules里添加以下代码:

           {
              test: lessRegex,
              exclude: cssModuleRegex,
              use: [
                ...getStyleLoaders(
                  {
                    importLoaders: 3,
                    sourceMap: isEnvProduction
                      ? shouldUseSourceMap
                      : isEnvDevelopment,
                  },
                  'less-loader'
                ),
                {
                  loader: 'style-resources-loader',
                  options: {
                    patterns: path.resolve(__dirname, lessGlobalUrl),
                  },
                },
              ],
              sideEffects: true,
            },

2.配置代理

安装中间件npm install http-proxy-middleware --save-dev
在src下新建文件:setupProxy.js,与App.js同级,简单配置如下:

const { createProxyMiddleware } = require('http-proxy-middleware');
const baseURL = "http://xxxxx.com";//要指向的服务器地址
module.exports = function (app) {
  app.use(
    createProxyMiddleware(
      '/api',
      {
        target: baseURL,
        changeOrigin: true
      }
    )
  )
}

axios文件改指向:

axios.create({
    // baseURL: (process.env.NODE_ENV === 'production' ? baseURL : '') + 'api',
    baseURL: 'api',
    headers: {
    },// 定义统一的请求头部
    timeout: 10000, // 配置请求超时时间
    withCredentials: true, // 如果用的JSONP,可以配置此参数带上cookie凭证,如果是代理和CORS不用设置
});
运行控制台报警告 image.png

虽然不影响热加载,但观感不好,解决方法如下:
找到webpackDevServer.config.js文件,把onBeforeSetupMiddleware和onAfterSetupMiddleware这两个方法替换成下面代码:

  setupMiddlewares: (middlewares, devServer) => {
      if (!devServer) {
        throw new Error("webpack-dev-server is not defined");
      }
      middlewares.unshift({
        name: 'evalSourceMapMiddleware',
        middleware: evalSourceMapMiddleware(devServer),
      });

      if (fs.existsSync(paths.proxySetup)) {
        // This registers user provided middleware for proxy reasons
        require(paths.proxySetup)(devServer.app);
      }

      middlewares.push({
        name: 'redirectServedPath',
        middleware: redirectServedPath(paths.publicUrlOrPath),
      });

      middlewares.push({
        name: 'noopServiceWorkerMiddleware',
        middleware: noopServiceWorkerMiddleware(paths.publicUrlOrPath),
      });

      return middlewares;
    }

3.useEffect重复调用的问题

解决方法:关闭严格模式,原因如下:


mmexport1681522623443.png

4.别名设置

webpack.config.js文件,找到modules.webpackAliases位置,配置示例如下:

      '@api': path.resolve(__dirname, '../src/api'),
      '@assets': path.resolve(__dirname,'../src/assets'),
      '@components': path.resolve(__dirname,'../src/components'),
      '@constants': path.resolve(__dirname, '../src/constants'),
      '@containers': path.resolve(__dirname,'../src/containers'),
      '@reducers': path.resolve(__dirname,'../src/reducers'),
      '@request': path.resolve(__dirname,'../src/request'),
      '@router': path.resolve(__dirname, '../src/router'),
      '@utils': path.resolve(__dirname,'../src/utils'),
      '@store': path.resolve(__dirname,'../src/store')

5.路由配置

路由菜单文件:

import Home from '@containers/Home'
import BasicLayout from '@containers/BasicLayout'
import Search from '@containers/Search';

// index 不能设置子路由,会报错
let routes = [
  {
    path: "/",
    element: <BasicLayout />,
    children: [
      { index: true, element: <Home /> },
      {
        path: "/search",
        element: <Search />
      }]
      }
]
export default routes;

App.js文件引入路由:

import React from 'react';
import { useRoutes } from 'react-router-dom'//新增
import router from '@router/router';

function App() {
  let element = useRoutes(router)//新增
  return (
      <div className='App'>
       {element}
      </div>
  );
}

export default App;

主文件入口index.js渲染节点:

import React from 'react';
import ReactDOM from 'react-dom/client';
import {BrowserRouter} from 'react-router-dom'
import App from './App.js';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  // 开启严格模式会双重渲染
  // <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  // </React.StrictMode>
);

6.路由跳转

注:不能定义在里层方法函数或者事件响应函数内,会报错,只能定义在主体函数里
Invalid hook call. Hooks can only be called inside of the body of a function component.

企业微信截图_16818686167281.png
常用的跳转方法:
import { useNavigate,useSearchParams,} from 'react-router-dom';
const navigate = useNavigate()
//第一种:search传递参数
navigate('/search?text=333')
//获取方法:用useSearchParams来获取
const [getSearchArr] = useSearchParams();
//第二种:params传递参数,路由也需要占位符配置
navigate('/article/17');
//获取方法:用useParams来获取
 const getParams = useParams();
//第三种:state属性携带参数
navigate('/search',{state: '测试'})
//获取方法:用useLocation来获取
const currentLocation = useLocation();
//获取url参数
const [params] = useSearchParams(); //获取url参数
params.get('text');//获取
params.set('');//设置
//获取location
 const location = useLocation();
console.log(location.pathname);

7.useState 更新异步的问题

场景:使用 useState 储存,当去改变这个数据的时候,每次拿到的都是上次的数据,无法实时更新。使用setTimeout延迟回调也失效。
原因:useState 返回的更新对象的方法是异步的,要在下次重绘才能获取新值,不要试图在更改状态之后立即获取状态。setState 只在合成事件和钩子函数中是“异步”的,在原生事件和setTimeout 中都是同步的。
解决方法:
1.使用useRef存储,useRef不仅可以用于访问 DOM 节点,也可以用来表示一个容器,current属性可以保存任何值,而且useRef返回的对象会在整个生命周期内保持。useRef 可以存储那些不需要引起页面重新渲染的数据。

    const [info, setInfo] = useState()
    const infoRef = useRef()
    useEffect(() => {
        infoRef.current = info
    }, [info])

2.重新定义一个数组来修改,在原数组上的修改不会引起组件的重新渲染,React 组件的更新机制对只进行浅对比,也就是更新某个复杂类型数据时只要它的引用地址没变,就不会重新渲染组件

const pushData = () => {
    setArr([...arr, 4])
}

注:函数组件中是不能通过异步来获取更新的值

useState和useRef区别: useState会触发重新渲染,useRef不会被重新声明,相当于this.xxx,render时机不应该更新ref.curent; useState是异步更新的,useRef是同步的;变量则是每次组件重新渲染的时候都会被重新进行赋值,要保留之前的操作状态就不要使用变量

3.useEffect监听值变化再触发回调,相当于componentDidUpdate

  useEffect(() => {
    if (category ) {
      // 调用搜索接口
      handleSearch();
    }
  }, [category])

8.路由懒加载,使用react自带的api

import { lazy } from "react";
const BasicLayout = lazy(() => import("@containers/BasicLayout")); 
const Home = lazy(() => import("@containers/Home"));
let routes = [
  {
    path: "/",
    element: <BasicLayout />,
    children: [
      { index: true, element: <Home /> }
    ]
  }
];

根元素一定要加上Suspense,不然会报错,Error: A React component suspended while rendering, but no fallback UI was specified.

import React,{Suspense} from 'react';
import { useRoutes } from 'react-router-dom'//新增
import router from '@router/router';
import { ConfigProvider,Spin } from 'antd';
import locale from 'antd/locale/zh_CN';

function App() {
  let element = useRoutes(router)//新增
  return (
    // 更改antd主题色
    <ConfigProvider locale={locale} theme={{
      token: {
        colorPrimary: '#22986E',
      },
    }}>
      <Suspense fallback={<Spin />}>
        <div className='App'>
        {element}
        </div>
      </Suspense>
    </ConfigProvider>

  );
}

相关文章

网友评论

      本文标题:2023-04-21 react hook从0搭建项目及开发总结

      本文链接:https://www.haomeiwen.com/subject/zqzrjdtx.html