Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么有时会在setState之后立即调用render,而有时不会_Javascript_Reactjs_React Native - Fatal编程技术网

Javascript 为什么有时会在setState之后立即调用render,而有时不会

Javascript 为什么有时会在setState之后立即调用render,而有时不会,javascript,reactjs,react-native,Javascript,Reactjs,React Native,这是我的密码: class TestState extends Component{ constructor(props){ super(props); this.state={ text:"123" } this._hello = this._hello.bind(this) } _hello(){ console.log("guangy will set stat

这是我的密码:

class TestState extends Component{
    constructor(props){
        super(props);
        this.state={
            text:"123"
        }
        this._hello = this._hello.bind(this)
    }

    _hello(){
        console.log("guangy will set state...");
        let num = Math.floor(Math.random()*100);
        this.setState({text: ""+num });
        console.log("guangy after set state...");
    }

    componentWillUpdate(){
        console.log("guangy componentWillUpdate")
    }

    render(){
        console.log("guangy render.....")
        return(<View>
            <Text>{this.state.text}</Text>
            <Button title="click" onPress={
                ()=>{
                    this._hello();
                }
            }/>
            <Button title="click1" onPress={
                ()=>{
                    setTimeout(()=>{
                        this._hello();
                    }, 10);
                }
            }/>
        </View>);
    }
}
并在单击第二个按钮时记录:

guangy will set state...
guangy componentWillUpdate
guangy render.....
guangy after set state...
我认为渲染函数应该被称为异步的,实际上在大多数情况下是异步的,就像我单击第一个按钮时一样,但是当我单击第二个按钮时,渲染函数似乎被称为同步的,因为“设置状态后”日志打印在“渲染”日志之后。为什么会发生这种情况?

根据

将setState()视为请求,而不是对 更新组件。为了获得更好的感知性能,可能会做出反应 延迟它,然后在一次过程中更新几个组件。反应 不保证立即应用状态更改。 setState()并不总是立即更新组件。可能 批处理或将更新推迟到以后。这使得阅读成为一种状态 就在调用setState()之后,这是一个潜在的陷阱

所以有人会认为
setState
是异步的。但如果我们看一些关键词,比如:

反应可能会延迟

setState()并不总是立即更新组件

它可以批处理更新或将更新推迟到以后

因此,我们是否认为
setState
可能是异步操作,也可能不是异步操作?
嗯,是的

这是源代码中的
setState

ReactComponent.prototype.setState = function(partialState, callback) {
  invariant(
    typeof partialState === 'object' ||
    typeof partialState === 'function' ||
    partialState == null,
    'setState(...): takes an object of state variables to update or a ' +
    'function which returns an object of state variables.'
  );
  this.updater.enqueueSetState(this, partialState);
  if (callback) {
    this.updater.enqueueCallback(this, callback, 'setState');
  }
};
看起来像是一个普通的同步函数,实际上是
setState
,因为它本身不是异步的,但它的执行效果可能是异步的

我自己做了一些测试,我意识到react只会在react控制整个流时异步更新状态,而react不能控制流,这意味着执行上下文在它之外,然后react会立即更新状态

那么,什么可以控制react的控制权呢?
类似于
setTimeout
setInterval
ajax请求和其他webApi的东西。
即使是附加到react外部的事件处理程序也会触发这种行为

事实上,这里有一个小片段可以满足我们的实验。
我有一个React组件
App
,它有一个带有
myValue
键的状态和一个名为
onClick
的方法
此方法记录当前状态,然后调用
setstate
,然后再次记录状态

App
呈现3个元素:

  • myValue
    的当前值
  • 我们通过react API单击
    onClick
    时附加的按钮
  • 我们通过
    addEventListener
    API单击
    onClick
    附加的按钮 (在你的思想之外)
当我们在react控制流时单击第一个按钮时,状态将异步更新

单击第二个按钮时,react将立即更新状态

类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
myVal:0
}
}
componentDidMount(){
const el=document.getElementById('btn');
el.addEventListener('click',this.onClick);
}
onClick=()=>{
console.log('Pre-setState',this.state.myVal);
this.setState({myVal:this.state.myVal+1});
console.log('Post setState',this.state.myVal);
console.log('-----------------');
}
render(){
const{myVal}=this.state;
返回(
{myVal}
由react管理
不是由react管理的
);
}
}
ReactDOM.render(,document.getElementById('root'))


原因是不渲染但设置状态是异步的,@ShubhamKhatri我知道设置状态是异步的,这就是为什么在“设置状态”之后打印“渲染…”,但在第二种情况下,为什么在设置状态之后立即调用渲染函数,看起来synchronousasync并不意味着后面的语句将在稍后执行,但它意味着任何事情都可能发生我猜这是关于“事件循环”的,setTimeout回调和render都是在帧事件循环结束时调用的,但是我不太了解reactNative在内部是如何工作的单击处理时这两个按钮之间没有区别,所以您会得到非常随机的结果,并且讨论它们为什么不同是没有意义的。很好的发现。有意义。@Sag1v您跟踪到“this.updater.enqueueSetState”了吗?我想了解它是如何在内部工作的,不幸的是我不知道更新程序的源代码在哪里?找到有趣的文章,我想你会喜欢它的
ReactComponent.prototype.setState = function(partialState, callback) {
  invariant(
    typeof partialState === 'object' ||
    typeof partialState === 'function' ||
    partialState == null,
    'setState(...): takes an object of state variables to update or a ' +
    'function which returns an object of state variables.'
  );
  this.updater.enqueueSetState(this, partialState);
  if (callback) {
    this.updater.enqueueCallback(this, callback, 'setState');
  }
};