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传参处理,跳转的实现,父子数据共享)的更多相关文章

  1. Tornado学习笔记(二) 路由/post/get传参

    本章我们学习 Tornado 的路由传参等问题 路由 路由的匹配 Tornado的路由匹配采用的是正则匹配 一般情况下不需要多复杂的正则,正则的基本规则如下(站长之家) 举个例子 (r'/sum/(\ ...

  2. Angular:路由的配置、传参以及跳转

    ①路由的配置 1.首先用脚手架新建一个项目,在路由配置时选择yes 2.用ng g component创建组件 3.在src/app/app-routing.module.ts中配置路由 import ...

  3. Nuxt的路由配置以及传参

    Nuxt 路由可以使用a标签进行链接跳转,例如我们创建了一个demo.vue的文件 <p> <a href="/demo">跳转去Demo页面</a& ...

  4. vue路由对不同界面进行传参及跳转的总结

    最近在做一个公众号的商城项目,主要用的VUE+MUI,其实今天这个点对于有过项目经验的前端工作者来说是最基础的,但也是必须要掌握的,今天小编主要是记录下传参和跳转的一些总结(仅供参考). 首先我们先上 ...

  5. Vue Router路由导航及传参方式

    路由导航及传参方式 一.两种导航方式 ①:声明式导航 <router-link :to="..."> ②:编程式导航 router.push(...) 二.编程式导航参 ...

  6. vue学习(6)-路由(导入包;创建子组件;创建路由对象)传参,子路由,多个组件

    后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源 前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换(不会刷新页 ...

  7. vue2.0路由写法、传参和嵌套

    前置知识请戳这里 vue-routerCDN地址:https://unpkg.com/vue-router@3.0.1/dist/vue-router.js vue-router下载地址:https: ...

  8. ionic简单路由及页面传参

    1)页面跳转及传参方法 angular.module('app.routes', [])//routes路由模型 .config(function($stateProvider, $urlRouter ...

  9. vue路由传参并跳转页面

    在vue项目中参数的传递可以使用本地缓存或者Vuex,那么vue能不能像小程序一样路由传参呢,显然是可以的而且非常简单 方式一:query传参 //传参 go(){ that.$router.push ...

  10. vue-router路由如何实现传参

    tip: 用params传参,F5强制刷新参数会被清空,用query,由于参数适用路径传参的所以F5强制刷新也不会被清空.(传参强烈建议适用string) 也可以选用sessionstorage/lo ...

随机推荐

  1. pandas之去重

    "去重"通过字面意思不难理解,就是删除重复的数据.在一个数据集中,找出重复的数据删并将其删除,最终只保存一个唯一存在的数据项,这就是数据去重的整个过程.删除重复数据是数据分析中经常 ...

  2. cf1809e(edu145e)

    1 /* 2 _ooOoo_ 3 o8888888o 4 88" . "88 5 (| -_- |) 6 O\ = /O 7 ____/`---'\____ 8 .' \\| |/ ...

  3. Windows服务器重启注意事项

    windows作为服务器有它的优势,但是相比于基于linux作为服务器来说,它不够稳定,这里的windows服务器作为服务器有各种版本,windows2012,2008,甚至还有2003,XP的系统, ...

  4. Django相关配置信息

    Django相关配置信息 1.配置数据库mysql 1.1 setting.py中配置信息 DATABASES = { 'default': { 'ENGINE': 'django.db.backen ...

  5. Nacos注册中心

    介绍 Nacos是SpringCloudAlibaba的组件,而SpringCloudAlibaba也遵循SpringCloud中定义的服务注册.服务发现规范.因此使用Nacos和使用Eureka对于 ...

  6. 记一次 Windows10 内存压缩模块 崩溃分析

    一:背景 1. 讲故事 在给各位朋友免费分析 .NET程序 各种故障的同时,往往也会收到各种其他类型的dump,比如:Windows 崩溃,C++ 崩溃,Mono 崩溃,真的是啥都有,由于基础知识的相 ...

  7. shell脚本编程(一)

    c81ba641-5ed7-4ab9-a7c0-e319e0f3890b 初识shell脚本编程 最近项目需求,需要了解下shell脚本编程,所以自己就必须玩玩了= = 初识shell脚本编程,找了几 ...

  8. 飞行时间技术TOF

    文章目录 飞行时间技术TOF 一. 光速的测定 二. 各种TOF技术 直接脉冲TOF 脉冲间接TOF 连续波调制TOF(Continous Wave TOF) 三. TOF技术的应用 飞行时间技术TO ...

  9. 在chatGPT的帮助下成功从Rancher中删除无效的集群

    只要你坚持,不放弃,问题总有解决的一天! 与chatgpt进行了几次沟通,成功解决历史遗留问题,成功从rancher中删除了无效的集群 chatGPT回答1 如果您在 Rancher UI 中无法删除 ...

  10. 代码打包的可视化数据分析图: webpack-bundle-analyzer 的使用

    先看webpack-bundle-analyzer的效果图(官方效果图): 通过使用webpack-bundle-analyzer可以看到项目各模块的大小,可以按需优化 1.先安装 npm insta ...