我在react-redux网站上遇到了一个重复模式:一个组件显示来自web api的数据,它应该在加载时自动填充,无需任何用户交互.
我想从容器组件启动异步提取,但据我所知,唯一的方法是从显示组件中的生命周期事件.这似乎使得无法将所有逻辑放在容器中,只使用哑无状态功能组件进行显示.
这意味着我不能将无状态功能组件用于任何需要异步数据的组件.这似乎不对.
似乎"正确"的方法是以某种方式从容器启动异步调用.然后,当调用返回时,状态将被更新,容器将获得新状态,然后将其传递给其无状态组件mapStateToProps()
.
进行异步调用mapStateToProps
和mapDispatchToProps
(我的意思是实际调用异步函数,而不是将其作为属性返回)没有意义.
所以我最终做的是将异步调用放在一个refreshData()
公开的函数中mapDispatchToProps()
,然后从两个或多个React生命周期方法中调用它:componentDidMount and componentWillReceiveProps
.
有没有一种干净的方法来更新redux存储状态而不在每个需要异步数据的组件中放入生命周期方法调用?
我是否应该将这些调用放在组件层次结构的更高位置(从而减少此问题的范围,因为只有"顶级"组件才需要监听生命周期事件)?
就这样,我对connect()ed容器组件的意思没有任何混淆,这是一个非常简单的例子:
import React from 'react';
import { connect } from 'react-redux';
import {action} from './actions.js';
import MyDumbComponent from './myDumbComponent.jsx';
function mapStateToProps(state)
{
return { something: state.xxxreducer.something };
}
function mapDispatchToProps(dispatch)
{
return {
doAction: ()=>{dispatch(action())}
};
}
const MyDumbComponentContainer = connect(
mapStateToProps,
mapDispatchToProps
)(MyDumbComponent);
// Uh... how can I hook into to …
Run Code Online (Sandbox Code Playgroud) 在进行handleSubmit
Ajax调用的redux-form 函数中,Ajax中需要一些Redux状态的属性(例如用户ID).
如果我想handleSubmit
在表单的组件中定义,这很容易:只需调用mapStateToProps
传入我需要的内容,并从this.props
我的内容中读取它handleSubmit
.
但是,像一个好的React-Redux开发人员一样,我编写了单独的视图组件和容器,因此我的视图组件可以很简单,几乎没有行为.因此,我想在我的容器中定义handleSubmit.
同样,简单 - redux-form被设置为这样做.定义一个onSubmit
in mapDispatchToProps
,表单将自动调用它.
哦,等等,mapDispatchToProps
没有办法访问redux状态.
好的,没问题,我只需要将我需要的道具handleSubmit
与表格值一起传递.
嗯,等等,handleSubmit
使用这种机制传递任何数据都是不可能的!你得到一个参数,values
并且无法添加另一个参数.
这留下了以下没有吸引力的替代方案(我可以验证1和2的工作原理):
1 在表单组件中定义一个提交处理程序,并从那里调用我自己从mapDispatchToProps传入的自定义提交处理函数.这没关系,但要求我的组件知道一些不需要显示表单的redux状态的道具.(此问题不是redux-form独有的.)
dumbSubmit(values)
{
const { mySubmitHandler, user} = this.props;
mySubmitHandler(values, user);
}
<form onSubmit={ handleSubmit(this.dumbSubmit.bind(this)) }>
Run Code Online (Sandbox Code Playgroud)
或者,更简洁地说,这可以组合成箭头函数:
<form onSubmit={ handleSubmit((values)=>{mySubmitHandler(values, this.props.user);}
Run Code Online (Sandbox Code Playgroud)
然后为了使这个处理程序完全不可知,它可以将整个this.props传递回自定义处理程序:
<form onSubmit={ handleSubmit((values)=>{mySubmitHandler(values, this.props);}
Run Code Online (Sandbox Code Playgroud)
2 在mergeProps中定义onSubmit而不是mapDispatchToProps,因此它可以访问stateProps.Dan Abramov建议不要使用mergeProps(出于性能原因),所以这似乎不是最理想的.
function mergeProps(stateProps, dispatchProps, ownProps) {
const { user } …
Run Code Online (Sandbox Code Playgroud) 我真正想要的是一个IsHitTestVisible版本,它忽略鼠标点击事件但仍然捕获鼠标进入和离开事件.
背景:无论何时,都会在控件下弹出信息覆盖.这是一个要求,所以我不能自由地删除这种行为.这是使用包含矩形形状的装饰器实现的,该装饰器填充有图像画笔.所有控件都以编程方式创建,不涉及XAML.
期望的行为:当用户将鼠标悬停在Rectangle上时,它应该变为部分透明.这样他们就可以看到叠加层下方的其他控件并单击它们.当用户点击叠加层时,点击应该传递到叠加层下面的任何控件,即用户点击的位置.
问题:如果我将IsHitTestVisible设置为True以允许鼠标点击通过,我不会获得MouseEnter事件.
是否有一种简单的方法可以让IsHitTestVisible保持True,然后将2-3个事件传递给adorner下面的正确控件?我正在寻找一个不涉及计算光标下方控件的解决方案,因为WPF显然能够为我做这个.
或者,我可以将IsHitTestVisible设置为False,然后使用另一种简单方法来确定鼠标何时在装饰器上方?
更新:我仍然希望得到答案,但截至目前,最有希望的解决方案似乎是保持IsHitTestVisible为真,并使用WPF命中测试API来确定鼠标光标下面的控件类型; 如果它是我所知道的,我会向它发送一个Click命令.不过,不确定这是否值得做; 截至目前,点击解除我的叠加层,因此用户只需点击两次.
谢谢!
我正在使用CIFilters将图像转换为灰度并应用一些图像处理效果.在UIImageView中显示输出有效; 图像显示并已按预期进行修改.
但是,每次调用UIImageJPEGRepresentation似乎都不会返回任何数据.它永远不会奏效.使用原始彩色图像调用UIImageJPEGRepresentation工作正常.
这里发生了什么?为什么显示图像时jpeg转换失败?不抛出任何异常(设置异常断点,它没有被命中)并且控制台中不显示任何消息.
let _cicontext = CIContext(options:nil)
// Set up grayscale and blur filters:
let grayIze = CIFilter(name: "CIColorControls")
let blur = CIFilter(name: "CIGaussianBlur")
grayIze.setValue(0, forKey:kCIInputSaturationKey)
grayIze.setValue(0.5, forKey: kCIInputBrightnessKey)
blur.setValue(4, forKey: kCIInputRadiusKey)
// Go!
let originalImage = CIImage(image: colorImageThatDefinitelyExists)
grayIze.setValue(originalImage, forKey: kCIInputImageKey)
blur.setValue(grayIze.outputImage, forKey: kCIInputImageKey)
let output = UIImage(CIImage: blur.outputImage)
let imageData: NSData? = UIImageJPEGRepresentation(output, 1.0) // Returns nil!?
Run Code Online (Sandbox Code Playgroud)
编辑:这是工作代码,基于Arbitur的答案:
// Define an image context at the class level, which will only be initialized once:
static let …
Run Code Online (Sandbox Code Playgroud) 我想在我的测试文件中模拟我的ES6类导入.
如果被模拟的类有多个使用者,那么将模拟移动到__mocks__可能是有意义的,这样所有测试都可以共享模拟,但在此之前我想将模拟保留在测试文件中.
jest.mock()
可以模拟导入的模块.传递单个参数时:
jest.mock('./my-class.js');
Run Code Online (Sandbox Code Playgroud)
它使用与模拟文件相邻的__mocks__文件夹中的模拟实现,或创建自动模拟.
jest.mock()
采用第二个参数,它是模块工厂函数.对于使用导出的ES6类export default
,不清楚此工厂函数应该返回什么.是吗:
default
是返回模仿类实例的对象的函数?文档很模糊:
第二个参数可用于指定正在运行的显式模块工厂,而不是使用Jest的自动锁定功能:
我正在努力想出一个工厂定义,当消费者import
是班级时,它可以作为构造函数.我一直在TypeError: _soundPlayer2.default is not a constructor
(例如).
我试过避免使用箭头函数(因为它们不能被调用new
)并让工厂返回一个具有default
属性(或不具有)的对象.
这是一个例子.这不起作用; 所有的测试都扔了TypeError: _soundPlayer2.default is not a constructor
.
正在测试的类: sound-player-consumer.js
import SoundPlayer from './sound-player'; // Default import
export default class SoundPlayerConsumer {
constructor() {
this.soundPlayer = new SoundPlayer(); //TypeError: _soundPlayer2.default is not a constructor
} …
Run Code Online (Sandbox Code Playgroud) 我有一个在Heroku上运行的Node Express应用程序,我希望使用LetsEncrypt的免费SSL证书进行加密.但是,我看到的方法需要打开端口443和80以允许ACME进程工作.
Heroku只给你一个端口,不允许你选择哪个端口.那么我该如何使用LetsEncrypt呢?
昨天我花了很多时间搞清楚这一点.很久以来第一次在StackOverflow上找不到我想做的事情的答案!
至少有两种使用SendGrid从Nodejs发送电子邮件的方法:
编辑2
所以,如果你现在开始一个项目,我会建议使用sendgrid-nodejs.
原始问题:
编辑以减少基于意见的问题:每种方法的优缺点是什么?我用谷歌搜索了几天,没看到两者的比较.还有另一个StackOverflow 问题要求区分两者(在其他几件事情中)没有得到答复.所以肯定这个问题的答案将有助于其他人.
我的具体用法,如果它有助于集中答案:我想允许iPhone应用程序的用户邀请其他人使用该应用程序.他们会在应用中看到默认的邀请文字,并可以对其进行自定义.自定义文本将发送到我的Nodejs服务器并添加到作业队列.处理队列时,会发送电子邮件.我希望电子邮件看起来不错,所以我想使用HTML电子邮件模板(以及明文交替主体).
在规模方面,这将开始非常小,但如果应用程序是succssful可以迅速扩大.
希望这是一个非常简单的问题:
我想创建一个包含我网站页面的完整URL的字符串,例如:
https://example.com/documents/1
理想情况下,我想在一个react-redux connect()
-ed容器中生成它mapStateToProps()
.页面是Route
使用browserHistory 的react-router的孙子(所以也许我可以从react-router或browserHistory以某种方式获取它?)如果有必要,我会在一个完整的React类中完成它.
但我不能为我的生活找到如何做到这一点.window
(如在window.location
)总是undefined
在mapStateToProps()
(没有什么大惊喜)和我的视图组件的render()
功能.
到目前为止,我只找到了访问当前路由的方法,例如"/ documents/1",这只是一个相对路径,不包含站点基本URL(https://example.com/)
我有一个只读的UITextView,我正在更新文本.当新文本出现时,我希望它按如下方式设置动画:新文本从右侧滑入,因为旧文本向左侧滑动.
是否可以使用transitionWithView执行此操作?如果没有,最好的方法是什么?我可以让它做一个CrossDissolve,但那不是我正在寻找的动画:
[UIView transitionWithView:self.storyTextView
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.storyTextView setText:withStory.storyText];
}
completion:nil];
Run Code Online (Sandbox Code Playgroud)
坚持左到右动画的原因是因为最终我希望用户能够通过在UITextView上向左滑动来触发它.
我有一个ViewController已经在InterfaceBuilder中配置为使用AutoLayout的所有子视图.布局工作正常.
我想使用UIDynamicAnimator提供的酷重力效果使其中一个子视图反弹.我认为这不适用于AutoLayout,但我尝试了它确实如此.它运作得很好!
我的问题是,这是预期的行为吗?是否会在某处造成问题?Apple是否提供有关组合AutoLayout和UIDynamicAnimators的任何指导?
这是代码,对任何感兴趣的人:
var boundaryFrame = self.buttonBackgroundView.frame
boundaryFrame = CGRect(x: 0,
y: boundaryFrame.origin.y + (boundaryFrame.height + 1),
width: self.view.frame.width,
height: 2)
self.animator = UIDynamicAnimator(referenceView: self.view)
var gravity = UIGravityBehavior(items: [self.buttonBackgroundView])
gravity.magnitude = 0.5
var collision = UICollisionBehavior(items: [self.buttonBackgroundView])
var boundaryId: NSMutableString = NSMutableString(string: "bottomBoundary")
let boundaryPath = UIBezierPath(rect: boundaryFrame)
collision.addBoundaryWithIdentifier(boundaryId, forPath: boundaryPath)
let bounceProperties = UIDynamicItemBehavior(items: [self.buttonBackgroundView])
bounceProperties.elasticity = 0.5
// Move it up before causing it to bounce down to its original location
self.setMeUpTopConstraint.constant = 10
self.view.setNeedsUpdateConstraints() …
Run Code Online (Sandbox Code Playgroud) ios ×3
react-redux ×3
reactjs ×3
node.js ×2
swift ×2
adorner ×1
animation ×1
autolayout ×1
cifilter ×1
ecmascript-6 ×1
express ×1
heroku ×1
iphone ×1
javascript ×1
jestjs ×1
lets-encrypt ×1
mouseevent ×1
nodemailer ×1
objective-c ×1
react-router ×1
redux ×1
redux-form ×1
sendgrid ×1
ssl ×1
uiimage ×1
uitextview ×1
wpf ×1