Javascript 通过更新程序回调而不是在React JS中传递对象来实际使用setState
React文档说明了以下内容:Javascript 通过更新程序回调而不是在React JS中传递对象来实际使用setState,javascript,reactjs,setstate,Javascript,Reactjs,Setstate,React文档说明了以下内容: 如果需要基于上一个状态设置状态,请阅读下面的更新程序参数 除了下面这句我不明白的话: 如果正在使用可变对象,并且在shouldComponentUpdate()中无法实现条件渲染逻辑,则仅当新状态与以前的状态不同时调用setState()将避免不必要的重新渲染 他们说: 第一个参数是带有签名(state,props)=>stateChange的更新程序函数状态是对应用更改时组件状态的引用 举个例子: this.setState((state, props) =&g
如果需要基于上一个状态设置状态,请阅读下面的更新程序参数
除了下面这句我不明白的话:
如果正在使用可变对象,并且在shouldComponentUpdate()中无法实现条件渲染逻辑,则仅当新状态与以前的状态不同时调用setState()将避免不必要的重新渲染
他们说:
第一个参数是带有签名(state,props)=>stateChange的更新程序函数状态是对应用更改时组件状态的引用
举个例子:
this.setState((state, props) => {
return {counter: state.counter + props.step};
});
说:
更新程序函数接收的状态和道具都保证是最新的。更新程序的输出与状态进行了浅层合并
保证最新的是什么意思?在决定是否使用更新程序函数(state,props)=>stateChange
或直接使用对象作为第一个参数时,我们应该注意什么
让我们假设一个真实的场景。假设我们有一个奇特的聊天应用程序,其中:
this.state={messages:[]}
表示李>
消息前面加上前缀李>
如果其他用户(不是当前用户)向当前用户发送消息,则新消息将从实时WebSocket连接到达当前用户,并附加到当前处于状态的消息中李>
如果发送消息的是当前用户,则在发送消息时激发的AJAX请求完成后,消息将被附加到第3点状态的消息中李>
让我们假设这是我们的FancyChat
组件:
import React from 'react'
export default class FancyChat extends React.Component {
constructor(props) {
super(props)
this.state = {
messages: []
}
this.API_URL = 'http://...'
this.handleLoadPreviousChatMessages = this.handleLoadPreviousChatMessages.bind(this)
this.handleNewMessageFromOtherUser = this.handleNewMessageFromOtherUser.bind(this)
this.handleNewMessageFromCurrentUser = this.handleNewMessageFromCurrentUser.bind(this)
}
componentDidMount() {
// Assume this is a valid WebSocket connection which lets you add hooks:
this.webSocket = new FancyChatWebSocketConnection()
this.webSocket.addHook('newMessageFromOtherUsers', this.handleNewMessageFromOtherUser)
}
handleLoadPreviousChatMessages() {
// Assume `AJAX` lets you do AJAX requests to a server.
AJAX(this.API_URL, {
action: 'loadPreviousChatMessages',
// Load a previous chunk of messages below the oldest message
// which the client currently has or (`null`, initially) load the last chunk of messages.
below_id: (this.state.messages && this.state.messages[0].id) || null
}).then(json => {
// Need to prepend messages to messages here.
const messages = json.messages
// Should we directly use an updater object:
this.setState({
messages: messages.concat(this.state.messages)
.sort(this.sortByTimestampComparator)
})
// Or an updater callback like below cause (though I do not understand it fully)
// "Both state and props received by the updater function are guaranteed to be up-to-date."?
this.setState((state, props) => {
return {
messages: messages.concat(state.messages)
.sort(this.sortByTimestampComparator)
}
})
// What if while the user is loading the previous messages, it also receives a new message
// from the WebSocket channel?
})
}
handleNewMessageFromOtherUser(data) {
// `message` comes from other user thanks to the WebSocket connection.
const { message } = data
// Need to append message to messages here.
// Should we directly use an updater object:
this.setState({
messages: this.state.messages.concat([message])
// Assume `sentTimestamp` is a centralized Unix timestamp computed on the server.
.sort(this.sortByTimestampComparator)
})
// Or an updater callback like below cause (though I do not understand it fully)
// "Both state and props received by the updater function are guaranteed to be up-to-date."?
this.setState((state, props) => {
return {
messages: state.messages.concat([message])
.sort(this.sortByTimestampComparator)
}
})
}
handleNewMessageFromCurrentUser(messageToSend) {
AJAX(this.API_URL, {
action: 'newMessageFromCurrentUser',
message: messageToSend
}).then(json => {
// Need to append message to messages here (message has the server timestamp).
const message = json.message
// Should we directly use an updater object:
this.setState({
messages: this.state.messages.concat([message])
.sort(this.sortByTimestampComparator)
})
// Or an updater callback like below cause (though I do not understand it fully)
// "Both state and props received by the updater function are guaranteed to be up-to-date."?
this.setState((state, props) => {
return {
messages: state.messages.concat([message])
.sort(this.sortByTimestampComparator)
}
})
// What if while the current user is sending a message it also receives a new one from other users?
})
}
sortByTimestampComparator(messageA, messageB) {
return messageA.sentTimestamp - messageB.sentTimestamp
}
render() {
const {
messages
} = this.state
// Here, `messages` are somehow rendered together with an input field for the current user,
// as well as the above event handlers are passed further down to the respective components.
return (
<div>
{/* ... */}
</div>
)
}
}
从“React”导入React
导出默认类FancyChat扩展React.Component{
建造师(道具){
超级(道具)
此.state={
信息:[]
}
this.API_URL='0http://...'
this.handleLoadPreviousChatMessages=this.handleLoadPreviousChatMessages.bind(this)
this.handleNewMessageFromOtherUser=this.handleNewMessageFromOtherUser.bind(this)
this.handleNewMessageFromCurrentUser=this.handleNewMessageFromCurrentUser.bind(this)
}
componentDidMount(){
//假设这是一个有效的WebSocket连接,允许您添加挂钩:
this.webSocket=新的FancyChatWebSocketConnection()
this.webSocket.addHook('newMessageFromOtherUsers',this.handleNewMessageFromOtherUser)
}
handleLoadPreviousChatMessages(){
//假设“AJAX”允许您对服务器执行AJAX请求。
AJAX(this.API_URL{
操作:“loadPreviousChatMessages”,
//在最早的消息下面加载以前的消息块
//客户端当前拥有或(`null`,初始)加载最后一块消息。
以下_id:(this.state.messages&&this.state.messages[0].id)| null
})。然后(json=>{
//需要在此处将消息前置到消息。
const messages=json.messages
//我们是否应该直接使用updater对象:
这个.setState({
messages:messages.concat(this.state.messages)
.sort(此.sortByTimestampComparator)
})
//或者像下面这样的更新程序回调原因(尽管我不完全理解)
//“更新程序函数收到的状态和道具都保证是最新的。”?
this.setState((状态,道具)=>{
返回{
messages:messages.concat(state.messages)
.sort(此.sortByTimestampComparator)
}
})
//如果用户在加载以前的消息时,也收到了新消息,该怎么办
//从WebSocket频道?
})
}
来自其他用户的HandlenewMessage(数据){
//由于WebSocket连接,“message”来自其他用户。
常量{message}=数据
//需要将消息附加到此处的消息。
//我们是否应该直接使用updater对象:
这个.setState({
messages:this.state.messages.concat([message])
//假设“sentTimestamp”是在服务器上计算的集中式Unix时间戳。
.sort(此.sortByTimestampComparator)
})
//或者像下面这样的更新程序回调原因(尽管我不完全理解)
//“更新程序函数收到的状态和道具都保证是最新的。”?
this.setState((状态,道具)=>{
返回{
消息:state.messages.concat([message])
.sort(此.sortByTimestampComparator)
}
})
}
来自当前用户的HandlenewMessage(messageToSend){
AJAX(this.API_URL{
操作:“newMessageFromCurrentUser”,
message:messageToSend
})。然后(json=>{
//需要将消息附加到此处的消息(消息具有服务器时间戳)。
const message=json.message
//我们是否应该直接使用updater对象:
这个.setState({
messages:this.state.messages.concat([message])
.sort(此.sortByTimestampComparator)
})
//或者像下面这样的更新程序回调原因(尽管我不完全理解)
//“更新程序函数收到的状态和道具都保证是最新的。
//
handleClick = () => {
//get a random color
const newColor = this.selectRandomColor();
//Set the state to this new color
this.setState({color:newColor});
//Change the background or some elements color to this new Color
this.changeBackgroundColor();
}