react ,@reduxjs/toolkit,react-redux

 

根组件index.js

import React from 'react';

import ReactDOM from 'react-dom/client';

import {RouterProvider} from "react-router-dom"

import router from "./router"

import { Provider } from "react-redux"

import store from './store';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(

    <Provider store={store}>

      <RouterProvider router={router}></RouterProvider>

    </Provider>

);

App.js  路由切换动画

app.js

import './App.scss';

import React from 'react';

import {Outlet,useOutlet,useLocation} from "react-router-dom"

import {CSSTransition,SwitchTransition} from "react-transition-group"

function App() {

  const currentOutlet = useOutlet();

  const location = useLocation()

  return (

    <div className="App">

      {/* <Outlet></Outlet> */}

      <SwitchTransition>

        <CSSTransition key={location.pathname} classNames="fade" timeout={ 1000 }>

          {

            ()=>(

              <div className="fade">{currentOutlet}</div>

            )

          }

        </CSSTransition>

      </SwitchTransition>

    </div>

  );

}

export default App;

App.scss

#root,

body,

html {

    width: 100%;

    height: 100%;

}

.App {

    width: 100%;

    height: 100%;

}

a {

    margin: 0 10px;

    text-decoration: none;

    color: #333;

}

.active {

    color: #c00;

}

.fade-enter {

    /* opacity: 0; */

    /* transform: scale(1.1); */

    transform: translateX(100%);

}

.fade-enter-active {

    /* opacity: 1; */

    /* transform: scale(1);

    transition: opacity 300ms, transform 300ms; */

    transform: translateX(0);

    transition: .3s;

}

.fade-exit {

    /* opacity: 1; */

    /* transform: scale(1); */

    transform: translateX(0);

}

.fade-exit-active {

    /* opacity: 0; */

    /* transform: scale(0.9);

    transition: opacity 300ms, transform 300ms; */

    transform: translateX(100%);

    transition: .3s;

}

redux

store index.js

import { configureStore } from "@reduxjs/toolkit"

import book from "./module/book"

const store=configureStore({

    reducer:book.reducer

})

export default store

book.js

import { createSlice } from "@reduxjs/toolkit"

const book=createSlice({

    name:"book",

    initialState:{

        book:[]

    },

    reducers:{

        addMyBook(state,{payload}){

            let idx=state.book.findIndex(item=>item.name===payload)

            if(idx===-1){

                state.book=[...state.book,{id:Date.now(),name:payload,isComplete:false}]

            }

        },

        comChange(state,{payload}){

            let idx=state.book.findIndex(item=>item.id===payload)

            state.book[idx].isComplete=!state.book[idx].isComplete

        }

    }

})

export const {addMyBook,comChange}=book.actions

export default book

router V6

index.js 拦截

import { createBrowserRouter,Navigate } from  "react-router-dom"

import Home from "../component/Home"

import MyBook from "../component/MyBook"

import App from "../App"

import Login from "../component/Login"

// 封装一个高阶组件(其实就是函数,这个函数要接收一个组件作为参数,返回一个组件)

const AuthComponent = props => {

    // 获取到当前组件

    const Com = props.children.type;

    // 判断token是否存在

    if(sessionStorage.token) {

      return <Com />

    } else {

      return <Navigate to="/login" />

    }

  }


 

const router=createBrowserRouter([

    {

        path:"/",

        element:<App/>,

        children:[

            {

                path:"/login",

                element:<Login/>

            },

            {

                path:"/home",

                element:<AuthComponent><Home/></AuthComponent>

            },

            {

                path:"/mybook",

                element:<AuthComponent><MyBook/></AuthComponent>

            },

            {

                path:"/",

                element:<Navigate to="/login"></Navigate>

            }

        ]

    }

])

export default router

组件 component

login.js

import React, { useState } from 'react';

import {useNavigate} from "react-router-dom"

const YourComponent = () => {

  const [phoneNumber, setPhoneNumber] = useState('');

  const [password, setPassword] = useState('');

  const [phoneNumberValid, setPhoneNumberValid] = useState(true);

  const [passwordValid, setPasswordValid] = useState(true);

  // 验证手机号码格式和位数

  const validatePhoneNumber = (value) => {

    const regex = /^1[3456789]\d{9}$/;

    return regex.test(value);

  };

  // 验证密码格式

  const validatePassword = (value) => {

    const regex = /^[A-Za-z][A-Za-z0-9]{5}$/;

    return regex.test(value);

  };

  // 处理手机号码输入变化

  const handlePhoneNumberChange = (e) => {

    const value = e.target.value;

    setPhoneNumber(value);

    setPhoneNumberValid(validatePhoneNumber(value));

  };

  // 处理密码输入变化

  const handlePasswordChange = (e) => {

    const value = e.target.value;

    setPassword(value);

    setPasswordValid(validatePassword(value));

  };

  // 渲染错误或正确图标

  const renderIcon = (valid) => {

    if (valid) {

      return <i className="icon-correct" />;

    } else {

      return <i className="icon-error" />;

    }

  };

  const navigate=useNavigate()

  const login=()=>{

    sessionStorage.setItem("token","123")

    navigate("/home")

  }

  return (

    <div>

      <label>手机号码:</label>

      <input

        type="text"

        value={phoneNumber}

        onChange={handlePhoneNumberChange}

      />

      {renderIcon(phoneNumberValid)}

      {!phoneNumberValid && <p>手机号码格式不正确</p>}

      <br />

      <label>密码:</label>

      <input

        type="password"

        value={password}

        onChange={handlePasswordChange}

      />

      {renderIcon(passwordValid)}

      {!passwordValid && <p>密码格式不正确</p>}

      <div>

      <button onClick={login}>登录</button>

      </div>

     

    </div>

  );

};

export default YourComponent;

home.js

import React ,{ useState } from 'react'

import { useEffect } from 'react'

import "./index.scss"

import {useDispatch,useSelector} from "react-redux"

import {useNavigate} from "react-router-dom"

import { addMyBook } from '../../store/module/book'

export default function Index() {

  const navigate=useNavigate()

  const dispatch=useDispatch()

  const [val,setVal]=useState("")

  const [list,setList]=useState([])

  const [book,setBook]=useState([

    {id:1,name:"红楼梦",img:"/img/1.jpg"},

    {id:2,name:"西游记",img:"/img/2.jpg"},

    {id:3,name:"水浒传",img:"/img/3.jpg"},

    {id:4,name:"三国演义",img:"/img/4.jpg"},

    {id:5,name:"笑面人",img:"/img/5.jpg"},

    {id:6,name:"拿破仑",img:"/img/6.jpg"},

    {id:7,name:"郭论",img:"/img/7.jpg"},

    {id:8,name:"呼啸山庄",img:"/img/8.jpg"},

  ])

  const getList=()=>{

    let arr=[...book]

    setList(arr)

  }

  useEffect(()=>{

    getList()

  },[])

  const keydown=(ev)=>{

    if(ev.keyCode===13){

     let arr= book.filter(item=>item.name.indexOf(val)>-1)

     console.log(arr);

     setList(arr)

     setVal("")

    }

  }

  const quxiao=()=>{

    let arr=[...book]

    setList(arr)

  }

  return (

    <div className='home'>

      <div className="header">

        <h3>书城</h3>

        <span onClick={()=>navigate("/mybook")}>我的书架</span>

      </div>

      <div className="search">

        <input type="text" value={val} onChange={(ev)=>setVal(ev.target.value)} onKeyDown={(ev)=>keydown(ev)}/>

        <button onClick={quxiao}>取消</button>

      </div>

      <div className="content">

        {

          list.map((item,index)=>(

            <div className="book" key={item.id}>

              <div className="img">

                <img src={item.img} alt="" />

              </div>

              <div className="n">

                <span>{item.name}</span>

                <button onClick={()=>dispatch(addMyBook(item.name))}>+</button>

              </div>

            </div>

          ))

        }

      </div>

    </div>

  )

}

mybook.js

import React,{ useState } from 'react'

import {useDispatch,useSelector} from "react-redux"

import {useNavigate} from "react-router-dom"

import "./index.scss"

import {DownOutlined,UpOutlined} from "@ant-design/icons"

import { comChange } from '../../store/module/book'

import { useEffect } from 'react'


 

export default function Index() {

  const [isShow,setIsShow]=useState(false)

  const [isShow2,setIsShow2]=useState(false)

  const dispatch=useDispatch()

  const navigate=useNavigate()

  const book=useSelector(store=>store.book)

  const com=()=>{

    setIsShow2(!isShow2)

  }

  const uncom=()=>{

    setIsShow(!isShow)

  }

  // useEffect(()=>{

  //   const book=useSelector(store=>store.book)

  // },[])

  return (

    <div className='mybook'>

      <div className="header">

        <h3>我的书架</h3>

        <span onClick={()=>navigate("/home")}>返回书城</span>

      </div>

      <div className="uncom">

        <div className="uncom_head">

          <span>未完成</span>

          {!isShow?<DownOutlined onClick={uncom}/>:<UpOutlined onClick={uncom} />}

         

        </div>

        {

            isShow?

            book.filter(item=>!item.isComplete).map(item=>(

              <div key={item.id}>

                <span>{item.name}</span>

                <button onClick={()=>dispatch(comChange(item.id))}>已看完</button>

              </div>

            )):

            <></>

          }

      </div>

      <div className="com">

        <div className="com_head">

          <span>已完成</span>

          {!isShow2?<DownOutlined onClick={com}/>:<UpOutlined onClick={com} />}

        </div>

        {

            isShow2?

            book.filter(item=>item.isComplete).map(item=>(

              <div>

                <span>{item.name}</span>

                <button onClick={()=>dispatch(comChange(item.id))}>再看一遍</button>

              </div>

            )):

            <></>

          }

      </div>

    </div>

  )

}

React 安装 ReduxRedux Toolkit 的步骤如下: 1. **安装Redux**: 首先需要安装Redux库。你可以使用npm或yarn来添加依赖。通过终端或命令行运行以下命令: ```bash npm install redux # 或者如果使用Yarn yarn add redux ``` 2. **安装Redux Toolkit (RTK)**: Redux Toolkit是一个官方推荐的库,它简化了Redux的工作流,包括创建store、action creators、reducers等。安装时同样使用npm或yarn: ```bash npm install @reduxjs/toolkit # 或者Yarn yarn add @reduxjs/toolkit ``` 安装完成后,你可以在React项目中创建Redux store,并配置基本的reducer和actions。例如,在`src/reducers/index.js`中: ```javascript import { createSlice } from '@reduxjs/toolkit'; // 创建一个简单的slice const counterSlice = createSlice({ name: 'counter', initialState: { count: 0 }, reducers: { increment: (state) => ({ count: state.count + 1 }), decrement: (state) => ({ count: state.count - 1 }), }, }); export default counterSlice.reducer; ``` 然后在`src/store.js`里创建并结合应用这个store: ```javascript import { configureStore } from '@reduxjs/toolkit'; import counterReducer from './reducers'; const store = configureStore({ reducer: { counter: counterReducer, }, }); export default store; ``` 最后,在你需要的地方可以使用`useSelector`和` useDispatch` hooks从store中获取数据和触发actions: ```jsx import React from 'react'; import { useSelector, useDispatch } from '@reduxjs/toolkit'; function Counter() { const count = useSelector((state) => state.counter.count); const dispatch = useDispatch(); return ( <div> <h1>Count: {count}</h1> <button onClick={() => dispatch(counterSlice.actions.increment())}>+</button> <button onClick={() => dispatch(counterSlice.actions.decrement())}>-</button> </div> ); } export default Counter; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值