React学习时,outlet 路由配置 (prop传参处理,跳转的实现,父子数据共享)
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
App.js文件
import { HashRouter, Routes, Route } from 'react-router-dom';
import Login from './page/login'
import Loginafter from './page/login/loginafter';
import Loginbefore from './page/login/loginbefore';
import Home from './page/home/home'
import About from './page/about/about'
import Integrated from './page/integrated/integrated'
import Sidebar from './page/sidebar/sidebar'
import Latent from './page/latent/latent'
import Particulars from './page/particulars/particulars'
import SecurityCheck from './page/securityCheck/securityCheck'
function App() {
{/* 如果需要默认显示页面将不需要填写路径 ,子路由不需要写/斜杠跳转时会带有*/}
return (
<HashRouter>
<Routes>
<Route path='/' element={<Login />} >
<Route path='' element={<Loginbefore />} ></Route>
<Route path='/Loginafter' element={<Loginafter />} ></Route>
</Route>
<Route path='/home' element={<Home />} ></Route>
<Route path='/about' element={<About />} >
<Route path='' element={<Integrated />} ></Route>
<Route path='sidebar' element={<Sidebar />} >
<Route path='' element={<Latent />} ></Route>
<Route path='particulars' element={<Particulars />} ></Route>
<Route path='securityCheck' element={<SecurityCheck />} ></Route>
</Route>
</Route>
</Routes>
</HashRouter>
);
}
export default App;
关于使用 outlet 会令prop无法准确的传达到子组件,提供案例如下
父组件案例【about.js】
import React from 'react';
import { Outlet, useNavigate } from 'react-router-dom';
export default function About() {
const navigate = useNavigate();
// let ddd = [{ sss: 2 }, { bbb: 4 }]
let ddd = 1;
const [count, setCount] = React.useState(ddd); //子组件对 setCount 操作后将被此处响应接收
return (
<>
{/* 跳转的同时 重定向默认页 */}
{/* navigate('integrated', {replace: true}); */}
{/* 跳转默认页 */}
{/* navigate('',); */}
{/* 变更父页 '/'+页名 */}
{/* navigate('/home') */}
{/* 跳转同级页 页名 */}
{/* navigate('sidebar') */}
{/* 跳转子页面 页名+'/子页名' */}
{/* navigate('sidebar/securityCheck', { state: ddd }); */}
{/* 实验,页面跳转时传入的参数,会不会随着刷新丢失? */}
{/* 结论: 依旧建议数据为接口返回的,当然,接收页(子组件)收到的数据并不会被刷新掉 */}
{/* 回到上一页 */}
{/* navigate(-1) */}
<div>
<h4>About</h4>
<button onClick={() => {
navigate('test', { state: ddd });
// state 传参不限制传参类型
}}>点击Test页</button>
</div>
{/* 以下为渲染子页面 */}
<Outlet context={[count, setCount]} />
</>
)
}
子组件案例【test.js】
import React, { Component } from 'react'
import { useOutletContext } from 'react-router-dom';
// outlet 状态共享
// 无状态子组件自身发生数据变化,同步给outlet上游组件 本文件以此实现数据共享
const Test = () => {
const [count, setCount] = useOutletContext();
console.log('count',count) //打印父数据
//useOutletContext 路由内置方法,监听数据发生变动
//数据类型任意 由上游 父组件决定
const increment = () => setCount((c) => c + 1); //操作父数据
return <button onClick={increment}>{count}</button>;
}
export default Test
在outlet实际摸索中,我的子组件对一则对象的某字段数据进行变更,他发生了报错。
即使outlet 共享了数据/状态,子组件初次渲染也拿到了,但超出局面的状况,可能是由于我有部分知识未能掌握,又或者由其他原因造成的。
查阅了网上一些博主的做法后,我尝试了使用 useEffect 异步更新,然并软。
this.forceUpdate() 强制更新,毕竟我实操变更后数据后,父组件成功打印了它。
然并软。(我猜测可能是子组件为无状态组件缘故,无生命周期导致数据变更的第一时间发生了请求...可以尝试用构造类组件写,当然useOutletContext只支持无状态组件内使用...)
有位博主的做法是,判定虚拟dom元素创建前,获取路由路径,这种做法挺高明的,我也是打算用一则案例写跳转时token的判定机制,和他的这种殊道同归,他也是以一种上下文的实现途径,只不过我是以v6的那种,他的写法上配置全局上下文,有点费时间,早期写过但版本不一致导致我这边报错过,所以我舍弃了旧写法。
但我依旧认为,一定有种很简别的方式实现数据变更,也许只是我没有想到而已...
最终,有一则报错告诉我,我可能需要将数据以数组包对象形式传递给子组件。
于是,我猜测,当我编辑后返回数据时,我可能需要push进去,再删除编辑前的数据,使我的无状态组件渲染时,不至于某行字段报null 或undefined。
至此,附上新案例:
父组件 login 文件夹下的 index.js
import React, { Component, useEffect } from 'react'
import { Outlet, useNavigate, useSearchParams } from 'react-router-dom';
const Btn = () => {
let state = {
token: 'asldfjdljfdsojdakf haiksf',
userName: 'zhangsan',
password: '123456'
}
// let state = 11
const [grossdata, setgrossdata] = React.useState([state])
// useEffect(() => {
// console.log('异步更新', grossdata)//监听数据发生了更改
// console.log('this',this)
// // this.forceUpdate()
// // if (!grossdata.token) {
// // console.log('判断')
// // // grossdata.token = <></>
// // // this.forceUpdate()
// // }
// }, [grossdata])
const navigate = useNavigate();
return <>
<button onClick={() => { navigate('Loginafter') }}>前往登录后</button>
<Outlet context={[grossdata, setgrossdata]} />
</>
}
export class index extends Component {
render() {
return (
<>
<h4>这是管理登录页和登录后页面的文件</h4>
<Btn></Btn>
</>
)
}
}
export default index
子组件 login 文件夹下的 loginafter.js
import React from 'react'
import { useOutletContext } from 'react-router-dom';
const Loginafter = () => {
const [grossdata, setgrossdata] = useOutletContext();
console.log('grossdata子组件打印', grossdata)
const increment = () => setgrossdata((c) => {
c[0].token = '';
let f = c[0]
return c.push(f) && c.splice(0, 1)
}); //操作父数据
return <>
<div>登录后</div>
<button onClick={increment}>清除token</button>
<br></br>
<span>{grossdata[0].token} </span>
<br></br>
<span>{grossdata[0].userName}</span>
<br></br>
<span>{grossdata[0].password}</span>
</>
}
export default Loginafter
我决定尝试,outlet 默认子组件操作 父组件事件...
补充:
对 useOutletContext 接收的数据,我起初只想着用,但在为对象做变更时报错,以致发现自己的无知,这使我做了许多无用功:this.forceUpdate() 强制更新, useEffect 异步更新 。
瞅下官网的说法:

官网原文链接: https://react.dev/learn/updating-objects-in-state
React学习时,outlet 路由配置 (prop传参处理,跳转的实现,父子数据共享)的更多相关文章
- Tornado学习笔记(二) 路由/post/get传参
本章我们学习 Tornado 的路由传参等问题 路由 路由的匹配 Tornado的路由匹配采用的是正则匹配 一般情况下不需要多复杂的正则,正则的基本规则如下(站长之家) 举个例子 (r'/sum/(\ ...
- Angular:路由的配置、传参以及跳转
①路由的配置 1.首先用脚手架新建一个项目,在路由配置时选择yes 2.用ng g component创建组件 3.在src/app/app-routing.module.ts中配置路由 import ...
- Nuxt的路由配置以及传参
Nuxt 路由可以使用a标签进行链接跳转,例如我们创建了一个demo.vue的文件 <p> <a href="/demo">跳转去Demo页面</a& ...
- vue路由对不同界面进行传参及跳转的总结
最近在做一个公众号的商城项目,主要用的VUE+MUI,其实今天这个点对于有过项目经验的前端工作者来说是最基础的,但也是必须要掌握的,今天小编主要是记录下传参和跳转的一些总结(仅供参考). 首先我们先上 ...
- Vue Router路由导航及传参方式
路由导航及传参方式 一.两种导航方式 ①:声明式导航 <router-link :to="..."> ②:编程式导航 router.push(...) 二.编程式导航参 ...
- vue学习(6)-路由(导入包;创建子组件;创建路由对象)传参,子路由,多个组件
后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源 前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换(不会刷新页 ...
- vue2.0路由写法、传参和嵌套
前置知识请戳这里 vue-routerCDN地址:https://unpkg.com/vue-router@3.0.1/dist/vue-router.js vue-router下载地址:https: ...
- ionic简单路由及页面传参
1)页面跳转及传参方法 angular.module('app.routes', [])//routes路由模型 .config(function($stateProvider, $urlRouter ...
- vue路由传参并跳转页面
在vue项目中参数的传递可以使用本地缓存或者Vuex,那么vue能不能像小程序一样路由传参呢,显然是可以的而且非常简单 方式一:query传参 //传参 go(){ that.$router.push ...
- vue-router路由如何实现传参
tip: 用params传参,F5强制刷新参数会被清空,用query,由于参数适用路径传参的所以F5强制刷新也不会被清空.(传参强烈建议适用string) 也可以选用sessionstorage/lo ...
随机推荐
- Java并发(二)----初次使用多线程并行提高效率
1.并行 并行代表充分利用多核 cpu 的优势,提高运行效率. 想象下面的场景,执行 3 个计算,最后将计算结果汇总. 计算 1 花费 10 ms 计算 2 花费 11 ms 计算 3 花费 ...
- TS(一)环境搭建与基本类型
1 TypeScript 环境搭建 1 准备NodeJs环境 2 npm全局安装typeScript npm i -g typescript 3 编写一个ts文件 4 使用tsc命令编译ts文件为js ...
- Redis分布式锁这样用,有坑?
背景 在微服务项目中,大家都会去使用到分布式锁,一般也是使用Redis去实现,使用RedisTemplate.Redisson.RedisLockRegistry都行,公司的项目中,使用的是Redis ...
- PYTHON数据分析——python基础
利用命令行创建python文件 C:\Users\Your Name>python myfile.py Python 变量命名规则: 变量名必须以字母或下划线字符开头 变量名称不能以数字开头 变 ...
- json解析异常显示{“$ref“:“$[0]“}
在编写测试代码实现一个组织架构树的功能时,部门的parent部门没有显示,出现了json解析异常错误[{"r e f " : " ref":"ref& ...
- Python-psycopg2的简单使用
一.简介 psycopg2 库是 python 用来操作 postgreSQL 数据库的第三方库. 二.安装 1.执行如下命令安装 pip3 install psycopg2 2.使用Pycharm安 ...
- 工作中,我们经常用到哪些SQL语句呢?
目录 一.DDL部分(create.drop.alter) 1.1 create 语句上 1.2 drop 语句 1.3 alter 语句 二.DML(数据操纵语言)和DQL(数据查询语言) 2.1 ...
- XUnit数据共享与并行测试
引言 在单元或者集成测试的过程中,需要测试的用例非常多,如果测试是一条一条过,那么需要花费不少的时间.从 V2 开始,默认情况下 XUnit 自动配置并行(参考资料),大大提升了测试速度.本文将对 A ...
- #Python实例 计算外卖配送距离(基于经纬度的导航及直线距离)
一:X-MIND 二:计算两点经纬度之间的距离 经纬度是利用三维球面空间来描述地球上一个位置的坐标系统,每个经纬度坐标由经度 lng 和纬度 lat 两个分量组成.经纬度的有效范围为经度-180度到+ ...
- 用go设计开发一个自己的轻量级登录库/框架吧(项目维护篇)
用go设计开发一个自己的轻量级登录库/框架吧(项目维护篇) 本篇将开始讲讲开发库/框架的最开始阶段,也就是搭建一个项目 源码:weloe/token-go: a light login library ...