react hook+ts+rouerV6 dev notes

2022-08-11 19:36:26 浏览数 (1)

1.React useHistory 更新为useNavigate如何传值

路由组件如何传值

1.组件跳转并传值

(1)导入

代码语言:javascript复制
import { useNavigate } from ‘react-router-dom’;

(2)使用

代码语言:javascript复制
const navigate = useNavigate();

点击事件中使用

 组件“/machine”为已经定义好的路由,state负责传值state:{参数:值}

代码语言:javascript复制
    navigate('/machine', {
      state: {
        from: '1'
      }
    })

(3)获取值

代码语言:javascript复制
导入import { useLocation } from ‘react-router-dom’;

使用

代码语言:javascript复制
let location = useLocation();
let server_id = location.state;

2.封装公共dialog的小技巧(children props使用)

首先独立封装一个antd的dialog

代码语言:javascript复制
import React, { useState } from 'react';
import { Modal, Button } from 'antd';
import CommonStyle from '../../../resources/styles/common.module.css'
const Dialog = (props: any) => {
  console.log(props)

  const { children } = props
  const [isModalVisible, setIsModalVisible] = useState(true);

  const showModal = () => {
    setIsModalVisible(true);
  };

  const handleOk = () => {
    setIsModalVisible(false);
  };

  const handleCancel = () => {
    setIsModalVisible(false);
  };
  return (

    <>
      <Modal footer={null} visible={isModalVisible} onOk={handleOk} onCancel={handleCancel} closable={false}>
        {children}
        {/* <div className={CommonStyle.modalNav}>
          <span className={`${CommonStyle.modalNavTitle}`}>
            <img className={`${CommonStyle.modalNaviImage}`} src="https://pickkiwi.s3.amazonaws.com/upload/ly1sYz9aM986CwIOOCQ6Kwxx2vSxJK5eOia16D8x6nLO7cWTDTk7jKSwCl3bj-Ku2AGKSd7l" alt="" />
            Request Product
          </span>
          <span className={`${CommonStyle.modalNavClose}`}><span className={`iconfont icon-exit ${CommonStyle.modalNavCloseIcon}`}></span></span>
        </div> */}

      </Modal>
    </>
  )
}

export default Dialog

然后在外面进行引用:

代码语言:javascript复制
      <Dialog>
        <div className={CommonStyle.modalNav}>
          <span className={`${CommonStyle.modalNavTitle}`}>
            <img className={`${CommonStyle.modalNaviImage}`} src="https://pickkiwi.s3.amazonaws.com/upload/ly1sYz9aM986CwIOOCQ6Kwxx2vSxJK5eOia16D8x6nLO7cWTDTk7jKSwCl3bj-Ku2AGKSd7l" alt="" />
            Request Product
          </span>
          <span className={`${CommonStyle.modalNavClose}`}><span className={`iconfont icon-exit ${CommonStyle.modalNavCloseIcon}`}></span></span>
        </div>
      </Dialog>

组件包裹的部分,

可以使用this.props.children来获取并显示

代码语言:javascript复制
const { children } = props
<Modal footer={null} visible={isModalVisible} onOk={handleOk} onCancel={handleCancel} closable={false}>
        {children}
 </Modal>

3.使用antd-form的内嵌组件(包括验证)

我们的想要的效果图:

代码:

代码语言:javascript复制
   <Form
        name="basic"
        layout="vertical"
        onFinish={onFinish}
        onFinishFailed={onFinishFailed}
      >
        <Form.Item
          label="Desired Cost"
        >
          <Input.Group compact>
            <Form.Item
              name={['DesiredCost', 'cost']}
              noStyle
              rules={[{ required: true, message: 'desiredCost is required' }]}
            >
              <Input style={{ width: 365 }} placeholder="$10.00" />
            </Form.Item>

            <Form.Item
              name={['DesiredCost', 'currency']}
              noStyle
              rules={[{ required: true, message: 'currency is required' }]}
            >
              <Select style={{ width: 100, marginLeft: 2 }}>
                {currencyOpts.map((opt: any, index: any) => <Option key={index} value={opt.value}>{opt.label}</Option>)}
              </Select>
            </Form.Item>

          </Input.Group>

        </Form.Item>
      </Form>

其实就是Form.Item里面套一个Input.group

然后再套Form.item就可以了,验证独自给form.item加上rules即可

参考文档:https://ant.design/components/form-cn/#header

4.重置antd-form

创建一个ref

代码语言:javascript复制
 const formRef: any = React.createRef()

挂载到form上(我的组件是通过子组件传值过去的)

传递给子组件

代码语言:javascript复制
 <RequestForm formRef={formRef} product={product} closeModal={closeModal} />

挂载

代码语言:javascript复制
     <Form
        ref={formRef}
      >

关闭dialog时重置表单(父组件方法)

代码语言:javascript复制
 const closeModal = () => {
    console.log(formRef)
    formRef.current.resetFields()
    setVisible(false)
  }

参考地址:https://blog.csdn.net/wsh2467991332/article/details/113850917

5.hook的useEffect 实现class的componentWillReceiveProps

代码语言:javascript复制
  useEffect(() => {
    _getRequests()
  }, [filterArgs])

filterArgs就是我们要传递的Props,如果这个传递的值更新了 就会触发UseEffect

小技巧:

一个hooks里面可以写多个useEffect

来处理不同的方法

代码语言:javascript复制
  useEffect(() => {
    _getRecentRequests()
  }, [])

  useEffect(() => {
    _getRequests()
  }, [filterArgs])

6.antd的上传组件 实现自定义上传(类似于element的自定义上传文件)

关键api:customRequest

上代码:

首先是elementUI的自定义上传代码(关注:http-request):

组件部分:

代码语言:javascript复制
       <el-upload
            action
            list-type="picture-card"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove"
            :http-request="setBase"
            accept=".jpg, .jpeg, .png, .gif, .JPG, .JPEG, .GIF"
            :limit="1"
          >
            <i class="el-icon-plus"></i>
          </el-upload>

方法:

代码语言:javascript复制
    setBase(e) {
      //   el-upload上传的图片是blob对象 把它转为为base64再进行上传 e.file是blob对象
      let params = new FormData();
      params.append("file", e.file);
      upload(params).then(res => {
        if (res.data) {
          this.title = e.file.name;
          this.IMGArr.push({
            name: res.data.filename,
            uid: e.file.uid
          });
        }
      });
    },

结束 就这么简单

然后是antd的自定义上传设置

首先是组件:(关注customRequest部分)

代码语言:javascript复制
       <Upload
          listType="picture-card"
          fileList={fileList}
          customRequest={this.handleChange}
        >
          <div className={Styles.uploadBtnHide} id="uploadBtnHide">Add Images</div>
        </Upload>

然后是方法拿到文件,然后就传递吧 下课!

代码语言:javascript复制
 handleChange = (event: any) => {
    console.log(event.file)
  }

完整的react antd组件上传demo

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/antd/4.18.8/antd.min.css
    "
    />
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/antd/4.18.8/antd.min.js"></script>

    <style>
      #uploadBtn {
        display: none;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>
  </body>
  <style></style>
  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          testVal: "123",
          fileList: [],
        };
      }

      render() {
        console.log(this);
        let { fileList } = this.state;
        return (
          <h1>
            <div id="uploadBtn">
              <antd.Upload
                listType="picture-card"
                customRequest={this.handleChange}
              >
                <antd.Button id="clickUploads"></antd.Button>
              </antd.Upload>
            </div>
            <antd.Button onClick={this.clickUpload}>
              Click to Upload
            </antd.Button>
            文件列表:
            <div>
              {fileList.map((item, index) => (
                <antd.Image width={200} key={index} src={item} />
              ))}
            </div>
          </h1>
        );
      }

      handleChange = (event) => {
        console.log(event.file);
        let { fileList } = this.state;
        const fd = new FormData();
        fd.append("file", event.file);
        fetch("http://biaoblog.run:3000/blogData/upload", {
          headers: {
            authorization:
              "Bearer xxx",
          },
          body: fd,
          method: "POST",
        })
          .then((res) => res.json())
          .then((res) => {
            console.log(res.filename);
            console.log(fileList);
            let newFileList = fileList;
            newFileList.push(res.filename);
            this.setState({
              fileList: newFileList,
            });

            console.log();
          });
      };

      clickUpload = () => {
        document.querySelector("#clickUploads").click();
      };
    }
    ReactDOM.render(<App />, document.getElementById("root"));
  </script>
</html>

7.antd-form中自动获取checkbox组件的值

需要在chekbox中添加一个属性:

valuePropName="checked"

代码语言:javascript复制
      <Form
        ref={formRef}
        name="basic"
        layout="vertical"
        onFinish={onFinish}
        onFinishFailed={onFinishFailed}
      >
       <Form.Item
          name="accept_similar"
          valuePropName="checked"
        >
          <Checkbox>Accept similar products</Checkbox>
        </Form.Item>
<Form>

8.react-redux 持久化 仓库配置(包含thunk)

代码语言:javascript复制
import { applyMiddleware, createStore } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunkMiddleware from 'redux-thunk'

import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web

import rootReducer from '../reducer'

const persistConfig = {
  key: 'root',
  storage,
}

const persistedReducer = persistReducer(persistConfig, rootReducer())

const store = createStore(persistedReducer, composeWithDevTools(applyMiddleware(thunkMiddleware)))

export const persistor = persistStore(store)
export default store

然后在App.js中进行引入

代码语言:javascript复制
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/es/integration/react'
import store, { persistor } from './redux/store/index'
import AppRouter from './router'
function App() {
  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <AppRouter />
      </PersistGate>
    </Provider>
  )
}

export default App

然后往仓库存储一个数据,刷新,发现持久化Ok了,下课

9.在react-hook中获取到redux仓库中的值(封装了thunk)

跟class的写法一样(前提是封装thunk)

先引用:

代码语言:javascript复制
import { connect } from 'react-redux'

然后使用:

代码语言:javascript复制
function mapStateToProps(state: any) {
  return {
    userInfo: state.app.currentUser.user
  }
}

export default connect(mapStateToProps)(AccountIndex);

然后在组件中获取:

代码语言:javascript复制
const AccountIndex = (props: any) => {
  console.log(props.userInfo) // props.userInfo就是仓库里面的数据
  return <Container>

  </Container>
}

结束!

10.一个Input的动态样式,可以参考

unclick:

click:

非常简单,想复杂了

11.antd-form 自定义校验

需求就是我们的验证码组件需要校验

可以用到form的自定义检验(就是拿到form的value和验证码 进行对比 然后抛错,挺方便)

代码语言:javascript复制
    <Form.Item
            name={["user", "code"]}
            label="验证码"
            rules={[
              { required: true },
              ({ getFieldValue }) => ({
                validator(_, value) {
                  console.log(SIdentifyRef);
                  if (value == SIdentifyRef.current.state.code) {
                    return Promise.resolve();
                  }
                  return Promise.reject(new Error("验证码错误"));
                },
              }),
            ]}
            style={{ width: 300 }}
          >
            <Row gutter={16}>
              <Col className="gutter-row" span={18}>
                <Input style={{ width: 200 }} />
              </Col>
              <Col className="gutter-row" offset={1} span={2}>
                <SIdentify ref={SIdentifyRef} />
              </Col>
            </Row>
          </Form.Item>

12.一个href的动画css效果

html

代码语言:javascript复制
    <a href="11111">哈哈哈哈</a>

css

代码语言:javascript复制
    a {
      text-decoration: none;
      border-bottom: 1px solid;
      border-bottom-color: #00000026;
      position: relative;
      display: inline-block;
      color: black;
    }

    a:after {
      content: "";
      position: absolute;
      bottom: -2px;
      left: 0;
      width: 0%;
      border-bottom: 2px solid currentColor;
      transition: width 0.5s ease;
    }
    a:hover:after {
      width: 100%;
    }

13.使用useMediaQuery来判断pc和mobile

代码语言:javascript复制
import useMediaQuery from '@/hooks/useMediaQuery'
const Login = () => {
  const isMobile = useMediaQuery('(max-width: 800px)')
  return (
    <Container className={Styles.loginContainer}>
      <Header className={Styles.loginHeader} showButtons={false} />
      <LoginForm />
      {
        !isMobile && <Footer />
      }
    </Container>
  );
}

14.使用lodash来判断数据是否存在(避免一些报错异常)

代码语言:javascript复制
import _ from 'lodash'
const ProductItem = (props: any) => {
  const { product, onRequest } = props

  return (
    <div className={Styles.similarPrdItem}>
      {!_.isEmpty(product.images) && (
       <YourCom/>
  )
}

0 人点赞