Javascript 通过更新程序回调而不是在React JS中传递对象来实际使用setState

Javascript 通过更新程序回调而不是在React JS中传递对象来实际使用setState,javascript,reactjs,setstate,Javascript,Reactjs,Setstate,React文档说明了以下内容: 如果需要基于上一个状态设置状态,请阅读下面的更新程序参数 除了下面这句我不明白的话: 如果正在使用可变对象,并且在shouldComponentUpdate()中无法实现条件渲染逻辑,则仅当新状态与以前的状态不同时调用setState()将避免不必要的重新渲染 他们说: 第一个参数是带有签名(state,props)=>stateChange的更新程序函数状态是对应用更改时组件状态的引用 举个例子: this.setState((state, props) =&g

React文档说明了以下内容:

如果需要基于上一个状态设置状态,请阅读下面的更新程序参数

除了下面这句我不明白的话:

如果正在使用可变对象,并且在shouldComponentUpdate()中无法实现条件渲染逻辑,则仅当新状态与以前的状态不同时调用setState()将避免不必要的重新渲染

他们说:

第一个参数是带有签名(state,props)=>stateChange的更新程序函数状态是对应用更改时组件状态的引用

举个例子:

this.setState((state, props) => {
  return {counter: state.counter + props.step};
});
说:

更新程序函数接收的状态道具都保证是最新的。更新程序的输出与状态进行了浅层合并

保证最新的是什么意思?在决定是否使用更新程序函数
(state,props)=>stateChange
或直接使用对象作为第一个参数时,我们应该注意什么

让我们假设一个真实的场景。假设我们有一个奇特的聊天应用程序,其中:

  • 聊天的状态由
    this.state={messages:[]}
    表示
  • 先前的消息通过AJAX请求加载,并在当前处于该状态的
    消息前面加上前缀
    
  • 如果其他用户(不是当前用户)向当前用户发送消息,则新消息将从实时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();
    }