setState(stateChange, [callback])------对象式的 setState
setState(updater, [callback])------函数式的 setState
import React, { Component } from 'react'
export default class SetState extends Component {
state = { count: 0 }
increment = () => {
// !组件的状态更新是异步的
// * 对象形式的 setState
// const { count } = this.state
// // setState() 第二个参数为render执行之后的回调
// this.setState({ count: count + 1 }, () => {
// console.log(this.state.count);
// })
// * 函数式的 setState
// setState(updateFn(state,props), cb) , 第二个参数cb为render执行之后的回调
this.setState((state, props) => {
// state 就是维护的状态,props为组件接收的属性值
// console.log(state, props);
return { count: state.count+1 }
},)
}
render() {
return (
<div>
<h2>当前求和为:{this.state.count}</h2>
<button onClick={this.increment}>点击+1</button>
</div>
)
}
}
setState 是函数式的 setState 的简写方式(语法糖)setState() 执行后获取最新的状态数据, 要在第二个 callback 函数中读取import React, { Component, lazy, Suspense } from 'react'
import { NavLink, Route } from 'react-router-dom'
//1.通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包
const Home = lazy(() => import('./Home'))
const About = lazy(() => import('./About'))
export default class Lazyload extends Component {
render() {
return (
<div>
{/* 编写路由链接 */}
<NavLink to='/home'>home</NavLink>
<NavLink to='/about'>about</NavLink>
{/* 注册路由 */}
{/*2.通过<Suspense>指定在加载得到路由打包文件前显示一个自定义loading界面*/}
{/* fallback 表示在跳转的过程中,展示的东西,可以是标签,或者一个组件(必须是正常引入的组件) */}
<Suspense fallback={loading...}>
<Route path="/home" component={Home}/>
<Route path="/about" component={About}/>
</Suspense>
</div>
)
}
}
lazy 函数和 Suspense 组件const Home = lazy(() => import('./Home'))<Suspense></Suspense> 包裹React.useState()React.useEffect()React.useRef()(1). State Hook: React.useState()
(2). Effect Hook: React.useEffect()
(3). Ref Hook: React.useRef()
const [xxx, setXxx] = React.useState(initValue)import React from 'react'
export default function Hook() {
// count 为初始值,setCount 为改变初始值的函数
// * 1. 为每一个状态单独开一个 useState()
// (官方建议为每一个状态单独进行管理,不推荐使用对象形式)
const [count, setCount] = React.useState(0)
// 点击 + 1
const increment = () => {
// 直接传入参数调用,就可以改变初始值
setCount(count + 1) // 第一种方式
// setCount((count) => count + 1) // 第二种方式
}
return (
<div>
<h2>当前求和为:{ count }</h2>
<button onClick={increment}>点击+1</button>
</div>
)
}
useEffect(() => {
// 在此可以执行任何带副作用操作
return () => { // 在组件卸载前执行
// 在此做一些收尾工作, 比如清除定时器/取消订阅等
}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
const refContainer = useRef()React.createRef() 一样import React from 'react'
export default function Hook() {
const [input, setInput] = React.useState('')
// * useRef(),创建一个容器,与类式组件中的createRef相同的用法
const myRef = React.useRef()
// 展示输入的数据
function show(e) {
setInput(e.target.value)
}
return (
<div>
<h2>你的输入:{input }</h2>
{/* ref 的值即为上面创建的 myRef 容器*/}
<input type="text" ref={myRef} onInput={show} placeholder='请输入'/>
</div>
)
}
import React, { Component, Fragment } from 'react'
export default class FragmentDemo extends Component {
render() {
return (
// 作用:可以不用必须有一个真实的DOM根标签了
// <></> 空标签也可以
// 如果要遍历,就使用Fragment,因为可以添加key值
<Fragment key={1}>
<input type="text" />
<input type="text" />
</Fragment>
)
}
}
一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信
const XxxContext = React.createContext()
<xxxContext.Provider value={数据}>
子组件
</xxxContext.Provider>
//第一种方式:仅适用于类组件
static contextType = xxxContext // 声明接收context
this.context // 读取context中的value数据
//第二种方式: 函数组件与类组件都可以
<xxxContext.Consumer>
{
value => ( // value就是context中的value数据
要显示的内容
)
}
</xxxContext.Consumer>
import React, { Component } from 'react'
import './index.css'
// 创建 Context 容器组件
const MyContext = React.createContext()
// 父组件
export default class A extends Component {
state = {
username: 'coderbin',
age: 21
}
render() {
const { username, age} = this.state
return (
<div className='parent'>
<h2>我是 A 组件</h2>
<h3>我的用户名是:{this.state.username}</h3>
{/* 注意:这里必须通过 value属性向后代传递数据 */}
<MyContext.Provider value={{username, age}}>
<B />
</MyContext.Provider>
</div>
)
}
}
// 子组件
class B extends Component{
render() {
return (
<div className='child'>
<h2>我是 B 组件</h2>
<C />
</div>
)
}
}
// 孙组件
// 类式组件接收数据的方法
// class C extends Component{
// // 声明接收 context
// static contextType = MyContext
// render() {
// const {username, age} = this.context
// return (
// <div className='grand'>
// <h2>我是 C 组件</h2>
// <h3>我是从A组件接收到的用户名:{username},年龄是:{ age }</h3>
// </div>
// )
// }
// }
// 函数式组件接收数据的方法
// 使用 <MyContext.Consumer> 包裹,在里面接收展示数据
function C() {
return (
<div className='grand'>
<h2>我是 C 组件</h2>
<h3>我是从A组件接收到的用户名:
<MyContext.Consumer>
{value => `${value.username},年龄是:${value.age}`}
</MyContext.Consumer>
</h3>
</div>
)
}
setState(),即使不改变状态数据, 组件也会重新 render() ==> 效率低shouldComponentUpdate() 总是返回 trueshouldComponentUpdate() 方法PureComponentPureComponent 重写了 shouldComponentUpdate(), 只有 state 或 props 数据有变化才返回 truePureComponent 来优化import React, { PureComponent } from 'react'
import './index.css'
// PureComponent 重写了 shouldComponentUpdate(),
// 只有 state 或 props数据有变化才返回true
// 注意:
// 只是进行state和props数据的浅比较, 如果只是数据对象内部数据变了, 返回false
// 不要直接修改state数据, 而是要产生新数据
export default class Parent extends PureComponent {
state = {
carName: '奔驰'
}
changeCar = () => {
this.setState({
carName: '法拉利'
})
}
// shouldComponentUpdate(nextProps, nextState) {
// // 当前值
// console.log(this.props, this.state);
// // 接下来要变化的目标 Props,目标 State
// console.log(nextProps, nextState);
// return true
// }
render() {
console.log('Parent -- render');
const { carName } = this.state
return (
<div className='parent'>
<h3>我是 Parent 组件</h3>
<span>我的车的名字是:{carName}</span><br />
<button onClick={this.changeCar}>点击换车</button>
<Child carName={carName} />
</div>
)
}
}
class Child extends PureComponent {
render() {
console.log('Child -- render');
return (
<div className='child'>
<h3>我是 Parent 组件</h3>
<span>我接收到的车是:{ this.props.carName }</span>
</div>
)
}
}
<A><B/></A><A> <B>xxxx</B></A>{this.props.children}<A render={(data) => <B data={data}></B>}></A>{this.props.render(内部state数据)}{this.props.data}import React, { Component } from 'react'
import './index.css'
export default class RenderProps extends Component {
render() {
return (
<div className='parent'>
<h3>我是 Parent 组件</h3>
{/* 1. 给 A 组件一个 render 属性,值为一个函数,里面返回 B 组件 */}
{/* 2. 这个函数可以接受一个来自 A 组件的参数,传递给 B 组件 */}
<A render={(name) => <B name={name} />} />
</div>
)
}
}
class A extends Component {
state = { name: 'coderbin'}
render() {
const { name } = this.state
return (
<div className='a'>
<h3>我是 A 组件</h3>
{/* 1. 接收传过来的 render,直接调用即可渲染 B 组件*/}
{/* 2. 调用的时候可以传递一个数据 */}
{this.props.render(name)}
</div>
)
}
}
class B extends Component {
render() {
console.log('接收到了 A 组件传递的数据:',this.props.name);
return (
<div className='b'>
<h3>我是 B 组件</h3>
</div>
)
}
}
getDerivedStateFromError 配合 componentDidCatch
// 生命周期函数,一旦后台组件报错,就会触发
static getDerivedStateFromError(error) {
console.log(error);
// 在render之前触发
// 返回新的state
return {
hasError: true,
};
}
componentDidCatch(error, info) {
// 统计页面的错误。发送请求发送到后台去
console.log(error, info);
}
import React, { Component } from 'react'
export default class Child extends Component {
state = {
users:[
{id:'001',name:'tom',age:18},
{id:'002',name:'jack',age:19},
{id:'003',name:'peiqi',age:20},
]
// 测试错误的情况
// users:'abc'
}
render() {
return (
<div>
<h2>我是Child组件</h2>
{
this.state.users.map((userObj)=>{
return <h4 key={userObj.id}>{userObj.name}----{userObj.age}</h4>
})
}
</div>
)
}
}
Parent.jsx
import React, { Component } from 'react'
import Child from './Child'
export default class Parent extends Component {
state = {
hasError:'' //用于标识子组件是否产生错误
}
//当 Parent的子组件出现报错时候,会触发 getDerivedStateFromError调用,并携带错误信息
static getDerivedStateFromError(error){
console.log('@@@',error);
return {hasError:error}
}
// 生命周期函数:组件挂载过程中,如果子组件出了错误,就会调用这个钩子
componentDidCatch(){
console.log('此处统计错误,反馈给服务器,用于通知编码人员进行bug的解决');
}
render() {
return (
<div>
<h2>我是Parent组件</h2>
{this.state.hasError ? <h2>当前网络不稳定,稍后再试</h2> : <Child/>}
</div>
)
}
}
每文一句:立志宜思真品格,读书须尽苦功夫。本文列举了对 React 的一些常用写法技巧。当然,关于 React 的这部分知识远远不仅如此,React 中我们需要掌握的知识还非常多。在后续的文章中也会继续跟各位分享更多的 React 知识。有疑问的小伙伴可以在评论区留言,大家一起探讨学习!
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做
我正在研究使用EventMachine支持的twitter-streamrubygem来跟踪和捕获推文。我对整个事件编程有点陌生。我如何判断我在事件循环中所做的任何处理是否导致我落后?有没有简单的检查方法? 最佳答案 您可以通过使用周期性计时器并打印出耗时来确定延迟。如果您使用的是1秒的计时器,您应该已经过了大约1秒,如果它更长,您就知道您正在减慢react器的速度。@last=Time.now.to_fEM.add_periodic_timer(1)doputs"LATENCY:#{Time.now.to_f-@last}"@
我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or
我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia
我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几
我有1.8.6附带的VanillaMacOSXLeopard。我是RoR的新手,所以会学习网上的教程。在使用更高版本的Ruby时,我是否可能会发现遵循它们的问题?我目前正在查看提到1.8.6和1.8.7的这个-http://www.railstutorial.org/book 最佳答案 RoR教程对两者都适用,但如果您正在学习Ruby,则应该学习1.9。Rails3将不支持1.8.6,所以我会选择1.8.7或1.9。我还推荐使用RVM在Ruby版本之间切换。 关于ruby-on-rail