一、React加载数据流程回顾

先看上一节的产品详情代码:https://blog.csdn.net/u010132177/article/details/103184176

【Pcontent.js】

import React, { Component } from 'react';
import axios from 'axios';
import '../css/pcontent.css';
import '../css/basic.css';
import {Link} from 'react-router-dom'; class Pcontent extends Component {
constructor(props){
super(props);
this.state={
detail_list:[], //此处要注意格式,如果Api是字典,就要设置成 {}
domain:'http://a.itying.com/'
}
} //【1】此处和上节稍有区别:把接口获取单独写成一个函数
requestData(id){
var api=this.state.domain+'api/productcontent?id='+id;
axios.get(api)
.then((response)=>{
console.log(response);
this.setState({
list:response.data.result[0]
})
})
.catch(function (error) {
console.log(error);
})
} //【2】在生命周期函数内调用获取api接口数据函数
componentDidMount(){
//id
console.log(this.props.match.params.id)
let id=this.props.match.params.id;
this.requestData(id);
} render() {
return (
<div className='pcontent'>
<div className="back"><Link to='/'>返回</Link></div> <div className="p_content">
<div className="p_info">
<img alt={this.state.detail_list.title} src={`${this.state.domain}${this.state.detail_list.img_url}`}/>
<h2>{this.state.detail_list.title}</h2>
<p className="price">{this.state.detail_list.price}元</p>
</div>
<div className="p_detial">
<h3>
商品详情
</h3>
{/*html解析写法*/}
<div className="p_content" dangerouslySetInnerHTML={{__html: this.state.detail_list.content}}>
</div>
</div>
</div> <footer className="pfooter">
<div className="cart">
<strong>数量:</strong>
<div className="cart_num">
<div className="input_left">-</div>
<div className="input_center">
<input type="text" readOnly="readonly" value="1" name="num" id="num" />
</div>
<div className="input_right">+</div>
</div>
</div>
<button className="addcart">加入购物车</button>
</footer>
</div>
);
}
}
export default Pcontent;

控制台:产品详情页get 404 undefined错误原因

上一节加载详情时,控制台将发现会报错:

GET http://a.itying.com/undefined 404 (Not Found) undefined

【原因】:

  • 分析源码发现,只有图片才会发起一个get请求

  • 这涉及到之前讲的生命同期函数加载顺序问题顺序:

    1. 先:componentWillMount(){}
    2. 再:render(){}
    3. 再:componentDidMount(){}
    4. 再:render(){} 一次
  • 原来,我们把获取Api数据放在第 3 步里,当第一次render(){}渲染时,Api数据还没获取到,因此会出现报错

    当第2次render之后,数据已获取,所以就能正常加载图片了。

  • 那么:放在willmount()里呢,一样拿不到,原因是,willmount可能会加载非常快

解决:

只要把图片加个判断,有图片,加载,没——渲染成空,写成这样即可:

此处语法三目:条件 ? true :false

{this.state.detail_list.img_url?<img alt={this.state.detail_list.title} src={`${this.state.domain}${this.state.detail_list.img_url}`}/>:''}

为什么在列表那里图片【home.js】就不会有404呢

原因:

  • 列表页用的是this.state.list.map函数,它首先会判断list是否有数据,有才会渲染图片
  • 没数据,不会渲染图片,也就不会有get 请求,也不会有404了
this.state.list.map((value,key)=>{
...
<img alt={v.title} src={`${this.state.domain}${v.img_url}`} />

二、react-router中用js跳转路由

实现js跳转路由:https://reacttraining.com/react-router/web/example/auth-workflow

  1. 要引入Redirect:
import {BrowserRouter as Router,Route,Link,Redirect,withRouter} from "react-router-dom";
  1. 定义一个flag
this.state = {loginFlag:false};
  1. render里面判断flag 来决定是否跳转:
if(this.state.loginFlag){
return <Redirect to={{ pathname: "/" }} />;
}
  1. 要执行js跳转:

    - 通过js改变loginFlag的状态

    - 改变以后从新render 就可以通过Redirect自己来跳转

代码示例

第1步:在首页加入登录按钮[home.js]

重点:

import {Link} from 'react-router-dom';
<Link to='Login'>登陆网站</Link>

【Home.js】

import React,{Component} from 'react';
import {Link} from 'react-router-dom';
import '../css/index.css';
import axios from 'axios'; //也可写成:const axios = require('axios'); class Home extends Component{
constructor(props){
super(props);
this.state={
list:[],
domain:'http://a.itying.com/'
}
} //获取Api接口的数据
getDataApi=()=>{
//拼装得到完整的Api接口链接
var api=this.state.domain+"api/productlist";
axios.get(api)
.then((response)=>{
console.log(response);
this.setState({
list:response.data.result
})
})
.catch(function(error){
console.log(error);
})
} //生周函数:页面渲染完成后加载
componentDidMount(){
//调用函数得到api接口数据
this.getDataApi();
} render(){
return(
<div>
{/*★★★本页面新加登陆按钮*/}
<Link to='Login'>登陆网站</Link>
<header className="index_header">
<div className="hlist">
<img alt='热销榜' src={require('../images/rexiao.png')} />
<p>热销榜</p>
</div> <div className="hlist">
<img alt='点过的菜' src={require('../images/caidan.png')} />
<p>点过的菜</p>
</div>
<div className="hlist">
<img alt='猜你喜欢' src={require('../images/sousuo.png')} />
<p>猜你喜欢</p>
</div>
</header> <div className="content">
{
this.state.list.map((value,key)=>{
return(
<div className="item" key={key}>
<h3 className="item_cate">{value.title}</h3>
<ul className="item_list">
{
value.list.map((v,k)=>{
return(
<li key={k}>
<div className="inner">
<Link to={`/Pcontent/${v._id}`}>
<img alt={v.title} src={`${this.state.domain}${v.img_url}`} />
</Link>
<p className="title">{v.title}</p>
<p className="price">{v.price}元</p>
</div>
</li>
)
})
} </ul>
</div>
)
})
}
</div> </div>
)
}
}
export default Home;

第2步:login.js

重点:【1-5】

import React, { Component } from 'react';
import {
BrowserRouter as Router,
Redirect, //【1】引入Redirect
} from "react-router-dom"; class Login extends Component {
constructor(props){
super(props);
this.state={
loginFlag:false //【2】设置登录标志
}
} //【4】登录函数
login=(e)=>{
e.preventDefault(); //阻止submit默认有个刷新的动作
let username=this.refs.username.value; //获取用户登录的用户名
let pwd=this.refs.pwd.value; //获取用户输入的密码
console.log(username,pwd)
if(username=='admin' && pwd=='admin'){ //如果用户名、密码都正确,把登录标志成 ture。
this.setState({loginFlag:true})
}else{alert('登录失败')}
} render() {
//【5】判断登录标志是否是ture,是就跳转到首页
if(this.state.loginFlag){
return <Redirect to='/' />;
}
return (
<div>
{/* 【3】登录表单,此处用ref获取值 */}
<form onSubmit={this.login}>
<input type='input' ref='username' /><br/>
<input type='password' ref='pwd' /><br/>
<input type='submit' value='登录' />
</form>
</div>
);
}
}
export default Login;

第3步:App页面把login.js加到路由里

import React from 'react';
//import './App.css';
import { BrowserRouter as Router, Route } from 'react-router-dom'; //引入路由模块
import Home from './components/Home';
import Pcontent from './components/Pcontent';
import Login from './components/Login'; function App() {
return (
<Router>
<div>
<Route exact path="/" component={Home} />
<Route path="/Pcontent/:_id" component={Pcontent} />
{/*★★★把登录路由加到此处*/}
<Route path="/Login" component={Login} />
</div>
</Router>
);
}
export default App;

最后,效果:

  1. 在Home点登录,会跳转到Login页面:登录网站
  2. 登录页面输入:admin,admin后,将自动跳转到首页,输入其它弹出登录失败

十六、React 渲染数据注意事项、以及react-router4.x中使用js跳转路由(登录成功自动跳转首页)的更多相关文章

  1. 从壹开始前后端分离 [ Vue2.0+.NetCore2.1] 二十六║Client渲染、Server渲染知多少{补充}

    前言 书接上文,昨天简单的说到了 SSR 服务端渲染的相关内容<二十五║初探SSR服务端渲染>,主要说明了相关概念,以及为什么使用等,昨天的一个小栗子因为时间问题,没有好好的给大家铺开来讲 ...

  2. SpringMVC(十六) 处理模型数据之SessionAttributes

    @SessionAttributes原理 默认情况下Spring MVC将模型中的数据存储到request域中.当一个请求结束后,数据就失效了.如果要跨页面使用.那么需要使用到session.而@Se ...

  3. react渲染数据3种方式

    直接渲染,()类似于模板字符串,包裹一个dom元素 ReactDOM.render( (<div> <h2>现在时间:{new Date().toLocaleTimeStrin ...

  4. WEB数据挖掘(十六)——Aperture数据抽取(9):数据源

    One of the central concepts of Aperture is the notion of a DataSource. A DataSource contains all inf ...

  5. SpringMVC(十六):如何使用编程方式替代/WEB-INF/web.xml中的配置信息

    在构建springmvc+mybatis项目时,更常用的方式是采用web.xml来配置,而且一般情况下会在web.xml中使用ContextLoaderListener加载applicationCon ...

  6. Python学习(二十六)—— Django基础一

    转载自:http://www.cnblogs.com/liwenzhou/p/8258992.html 一.Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的 ...

  7. Python之路【第十六篇】Django基础

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  8. Django(十六)基于模板的登录案例:登录装饰器、csrf攻击方式及防护、ajax的Post 的csrf开启写法、生成验证码、加验证码登录、反向解析+传参

    一.csrf攻击 1.1 csrf攻击(跨站请求伪造) [csrf攻击即]:通过第3方网站,伪造请求(前提条件是你已经登录正常网站,并保存了session或cookie登录信息且没有退出),第三方网站 ...

  9. NeHe OpenGL教程 第三十六课:从渲染到纹理

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

随机推荐

  1. Linux 下面搭建KMS服务器

    1. 下载安装Linux 版的KMS服务软件 # wget https://github.com/Wind4/vlmcsd/releases/download/svn1111/binaries.tar ...

  2. 【PAT甲级】1016 Phone Bills (25 分)(结构体排序)

    题意: 输入24个正整数代表从0到23每个小时通话一分钟花费的美分.输入一个正整数N(<=1000),然后输入N组字符串,每个字符串包含客户的名字和通话的时刻以及打出或者挂断的状态. 按照字典序 ...

  3. 「Luogu P3680 凸轮廓线」

    一道神奇的计算几何题 前置芝士 正三角形,正方形,圆:什么,您都会,那真是太好了. 三角函数的运用:因为我不是很想在这一块写太多,具体可以自行百度. 推导公式 对于一串是圆和正方形开头和结尾时是十分好 ...

  4. luogu P2754 [CTSC1999]家园

    本题是分层图最大流问题,相当于按时间拆点,每个当前点向下一点的下一时间层连点,每一层有n+1个点 #include<bits/stdc++.h> using namespace std; ...

  5. Docker如何使用nginx搭建tomcat集群

    首先创建tomcat的文件夹 , 为了方便docker的配置 我这里直接在根目录中创建 第一步:创建文件夹:发布文件夹 mkdir -p /docker/tomcat/webapp8081 mkdir ...

  6. Altium Designer中,将多个工程下的原理图和PCB合并在一起

    TDD双向放大器的设计分为三部分:LNA部分.PA部分和控制开关部分.为了调试方便,已经在三个Altium工程里面分别设计了三部分.现在需要合并成一个板子,为了保留已有的布局布线的工作量,采用这个办法 ...

  7. pytorch神经网络解决回归问题(非常易懂)

    对于pytorch的深度学习框架,在建立人工神经网络时整体的步骤主要有以下四步: 1.载入原始数据 2.构建具体神经网络 3.进行数据的训练 4.数据测试和验证 pytorch神经网络的数据载入,以M ...

  8. 【剑指Offer面试编程题】题目1521:二叉树的镜像--九度OJ

    题目描述: 输入一个二叉树,输出其镜像. 输入: 输入可能包含多个测试样例,输入以EOF结束. 对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000,n代表将要输入的二叉树节点 ...

  9. Java的equals方法实现及其细节

    判断两个对象是否等价,是OOP编程中常见的需求(下面围绕Java来进行阐述). 考虑这样几种情况:通过某个特征值来判断两个对象是否“等价”,当这两个对象等价时,判断结果为true,否则结果为false ...

  10. 用 lastIndexOf()、substr()、split()方法截取一段字符串

    lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索. split() 方法用于把一个字符串分割成字符串数组,抽取到分割符前面部分. subst ...