当我用酶测试类组件时,我可以wrapper.setState({})设置状态。当我用useState()钩子测试功能组件时,现在该怎么做?
例如,在我的组件中,我有:
const [mode, setMode] = useState("my value");
Run Code Online (Sandbox Code Playgroud)
我想改变mode测试范围
我handleSelection点击了一个按钮时调用的方法,但是,如果在达到状态时没有设置状态,则单击按钮this.setState({selectedFoods: newSelections});.方法中的其他所有内容都正确执行(因为我的各种console.logs告诉我:)).当第二次单击该按钮时,方法中的所有内容都会再次执行并且setState工作正常.
var Flavor = React.createClass({
getInitialState: function() {
return { foods: {}, selectedFoods: [], affinities: [] };
},
componentDidMount: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({foods: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidUpdate: function () {
$('#select-food').selectize({
onChange: this.handleSelection
}
);
},
handleSelection: function (e) {
if (e.target) {
var selectedFood = e.target.id;
} else {
var selectedFood = e; …Run Code Online (Sandbox Code Playgroud) 为什么React中没有异步getState函数?
文档告诉我们setState是异步的.很好,但这意味着我们无法安全地使用this.state,我们需要一个异步getState来尊重执行顺序.
根据我的理解,我们永远不应该使用this.state并使用这样的getState函数:
getState(callback) {
this.setState((prevState) => {
callback(prevState) ;
});
}
...
this.getState((curState) => {
// we now can use the current state safely
}
Run Code Online (Sandbox Code Playgroud)
在我的思维方式中,我在这里缺少什么?为什么React中不存在这样的功能?
- 编辑 -
正如我的一位朋友告诉我的那样,目前尚不清楚,因为我不相信第一个答案,让我们分析一些代码:
simpleFunc() {
setState({ "counter" : 1 });
setState({ "counter" : 2 });
this.state.counter // => no garanty about the value
getState((curState) => { // ensure curState.counter is 2 });
}
Run Code Online (Sandbox Code Playgroud)
这个简单的例子表明我们不能直接在所有情况下使用this.state,因为setState是异步的.
这是一个可以使用getState的计数器示例:http://codepen.io/Epithor/pen/ZLavWR?edit = 0010#0
简短的回答:糟糕的实践,甚至不确定getState给我们当前的
解决方法很简单,但事实上我们可以分解一些函数并使用它们而不关心上下文似乎很有趣,不是吗?
因此,当许多事件以特定顺序发生时,一些事件会改变状态,一些事件会读取状态:如何确定,当事件读取状态时使用this.state读取良好状态,因为所有更改都是异步的?
事实上所有都是关于时间的:
T : …Run Code Online (Sandbox Code Playgroud) 我的代码有效,但我有一个最佳实践问题:我在状态中有一个对象数组,用户交互将一次更改一个对象的值.据我所知,我不应该直接改变状态,我应该总是使用setState.如果我想以任何代价避免这种情况,我将通过迭代深度克隆数组,并更改克隆.然后将状态设置为克隆.在我看来,避免改变我以后会改变的状态只会降低我的表现.
详细版本:
this.state.data是一个对象数组.它代表论坛中的主题列表,收藏夹按钮将切换,调用clickCollect().由于我在状态中有一个数组,当我更改一个项的is_collected属性时,我需要创建一个要使用的数组的副本,并在更改为新值后,我可以将其设置为状态.
Run Code Online (Sandbox Code Playgroud)var data = this.state.data.slice(0); data[index].is_collected = !data[index].is_collected; this.setState({data: data});
var data = this.state.data:这会将指针复制到数组,push(),shift()等会直接改变状态.双方data并this.state.data会受到影响.
var data = this.state.data.slice(0):这使得浅层克隆,推送和移位不会改变状态,但在我的克隆中,我仍然有指向状态数组元素的指针.所以,如果我改变data[0].is_collected,this.state.data[0].is_collected也会改变.这发生在我打电话之前setState().
通常我应该这样做:
Run Code Online (Sandbox Code Playgroud)var data = []; for (var i in this.state.data) { data.push(this.state.data[i]); }
然后我更改index的值,当它为false时将其设置为true,否则为true时:
Run Code Online (Sandbox Code Playgroud)data[index].is_collected = !data[index].is_collected;
并改变状态:
Run Code Online (Sandbox Code Playgroud)this.setState({data: data});
考虑我的阵列相对较大或非常大,我想这次迭代会降低我的APP的性能.如果我知道这是出于任何原因的正确方法,我会支付这笔费用.但是,在这个函数(clickCollect)中,我总是将新值设置为状态,我不是在等待一个错误的API响应,它会说停止进行更改.在所有情况下,新值都将进入状态.实际上我setState只调用UI再次渲染.所以问题是:
for var i in ...).slice(0)如果我的数组包含对象,那么生成浅层clone()是否有意义?正在对数组内部的对象进行更改,因此浅层克隆仍会更改我的状态,就像copy(data = this.state.data)一样.为简单起见,我的代码被简化并且API调用被删除.
这是一个初学者的问题,所以也欢迎采用完全不同的方法.或链接到其他问答.
Run Code Online (Sandbox Code Playgroud)import React from …
我有一个有状态的小部件,它有一个简单的网格,每个网格单元都有一个容器.
我想点击一个单元格/容器并更改其内容.
问题是GestureDetector - > onTap方法在所有cels的app刷新时被触发.
在下面的示例中,该_changeCell方法立即针对所有cels触发,onTap但不起作用.
有任何想法吗?
import 'package:flutter/material.dart';
class GridWidget extends StatefulWidget {
@override
_GridWidgetState createState() => new _GridWidgetState();
}
class _GridWidgetState extends State<GridWidget> {
@override
Widget build(BuildContext context) {
Color cellColor = Colors.white;
Text cellText = new Text('');
// when a cell is tapped, change the color and text
_changeCell(index) {
setState(() {
cellColor = Colors.lightBlue;
cellText = new Text('clicked');
});
print("Container clicked " + index.toString());
}
// create a 5 by 5 …Run Code Online (Sandbox Code Playgroud) 我有一个根类RootPage,StatefulWidget它始终在视图中.我想改变body的RootPage是通过控制RootPage's currentPage Widget从不同的类,如我的FeedPage类和其他类,我做什么呢?
示例代码
import 'package:flutter/material.dart';
class RootPage extends StatefulWidget {
@override
_RootPageState createState() => new _RootPageState();
}
class _RootPageState extends State<RootPage> {
FeedPage feedPage;
Widget currentPage;
@override
void initState() {
super.initState();
feedPage = FeedPage();
currentPage = feedPage;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
//Current page to be changed from other classes too?
body: currentPage
);
}
}
class FeedPage extends StatefulWidget {
@override
_feedPageState …Run Code Online (Sandbox Code Playgroud) 在等待另一个功能并将状态记录到控制台后调用setState时,该值立即可用。
我知道setState是异步的,在所有其他情况下,调用它后将不会立即可用(但在setState回调中将可用)
不用等待时使用(预期)
// inital value state is 0
const response = fetchSomething()
this.setState({
value: 5
})
console.log(this.state.value) // prints 0
Run Code Online (Sandbox Code Playgroud)
与await一起使用
// inital value state is 0
const response = await fetchSomething()
this.setState({
value: 5
})
console.log(this.state.value) // prints 5
Run Code Online (Sandbox Code Playgroud)
我在这里想念什么?
如果我将变量声明为最终变量,那么我想更改(按下时)的值(变量)就在其中,setState(){}以便可以更改这些变量,该怎么做才能防止这种情况发生?
还有,为什么这么写widget.value?
我试过用 static 而不是 final 不起作用
class BottomCard extends StatefulWidget {
String title;
int value;
@override
_BottomCardState createState() => _BottomCardState(); }
class _BottomCardState extends State<BottomCard> {.....
....<Widget>[
FloatingActionButton(
elevation: 0,
child: Icon(FontAwesomeIcons.plus),
onPressed: () {
setState(() {
widget.value++;
});
},
backgroundColor: Color(0xFF47535E),
),
Run Code Online (Sandbox Code Playgroud) 我知道我不应该直接在React中改变状态,但是当我使用函数时情况怎么样:
onSocialClick = e => {
const id = e.target.value;
this.setState((prevState, props) => {
prevState[id] = !(prevState[id]);
return prevState;
});
};
Run Code Online (Sandbox Code Playgroud)
修改传递的对象是错误的吗?
编辑:
事实证明,我们大多数人在这里都错了.React docs现在清楚地说明了这一点:
state是对应用更改时组件状态的引用.它不应该直接变异.相反,应该通过基于state和props的输入构建新对象来表示更改
感谢@TomášHübelbauer在评论中指出它.
我正在使用此问题中的方法来更改颤振中 Scaffold 的主体:
Flutter Drawer Widget - 更改 Scaffold.body 内容
所描述的方法非常有效。现在我只想在用户点击其中一个项目后自动关闭抽屉。
我尝试使用 Navigator.pop() 方法,但它会弹出整个屏幕,而不仅仅是抽屉。它让我看到一个全黑的屏幕。
有什么建议?
setstate ×10
reactjs ×6
flutter ×4
dart ×3
javascript ×3
asynchronous ×2
arrays ×1
async-await ×1
class ×1
drawer ×1
enzyme ×1
getstate ×1
react-hooks ×1
scaffold ×1
state ×1