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. 扯下@EventListener这个注解的神秘面纱。

    你好呀,我是歪歪. 前段时间看到同事在项目里面使用了一个叫做 @EventListener 的注解. 在这之前,我知道这个注解的用法和想要达到的目的,但是也仅限于此,其内部工作原理对我来说是一个黑盒, ...

  2. 被吐槽 GitHub仓 库太大,直接 600M 瘦身到 6M,这下舒服了

    大家好,我是小富- 前言 忙里偷闲学习了点技术写了点demo代码,打算提交到我那 2000Star 的Github仓库上,居然发现有5个Issues,最近的一条日期已经是2022/8/1了,以前我还真 ...

  3. 如何在 .NET Core WebApi 中处理 MultipartFormDataContent 中的文件

    在上一篇文章(如何在 .NET Core WebApi 中处理 MultipartFormDataContent)中,我们有描述过如何以最简单的方式在 .NET Core WebApi 中处理 Mul ...

  4. .NET Web入门到高级路线(新版本)

    .NET Web入门到高级路线 C# 基础语法 .NET Core 基础知识 ASP.NET Core基础知识概述 Blazor ASP.NET Core 官方文档 ORM FreeSql Entit ...

  5. js中宏任务和微任务

    宏任务包括:<script>整体代码.setTimeout.setInterval.setImmediate.Ajax.DOM事件微任务:process.nextTick.Mutation ...

  6. JS 实现关键字文本搜索 高亮显示

    示例:  利用字符串的 split 方法,通过搜索的关键字分割成数组  在利用数组的 join 方法拼接成字符串 我是利用mock的省份 1 <template> 2 <div cl ...

  7. vivo 推送系统的容灾建设与实践

    作者:vivo 互联网服务器团队 - Yu Quan 本文介绍了推送系统容灾建设和关键技术方案,以及实践过程中的思考与挑战. 一.推送系统介绍 vivo推送平台是vivo公司向开发者提供的消息推送服务 ...

  8. 高精度地形DEM数据下载(NASA数据 12.5米分辨率)

    本文介绍从NASA阿拉斯加卫星设备处网站下载高精度DEM数据,下载的数据精度是12.5米分辨率. 目前国内大部分可以下载的dem数据都是30米或90米分辨率的,对于更高精度的数据要不就是需要付费下载, ...

  9. Grafana系列-统一展示-6-Zabbix仪表板

    系列文章 Grafana 系列文章 Notes: 关于 Grafana系列-统一展示-6-Zabbix 数据源, 其实已经在之前的文章: 使用 Grafana 统一监控展示 - 对接 Zabbix 里 ...

  10. Vue中使用富文本编辑器

    原文链接:https://blog.csdn.net/qq_45695853/article/details/114635009