is it ok to change the route programatically inside an epic in redux-observable - react-router

I am using redux-observable and in my epics I am changing the route in some of them using browserHistory.push. Is this standard/good practice? my gut feeling tells no, however need your opinion. In addition to this after upgrading to react-router 4, I cannot get access to browserHistory how do I do this?

Imperatively calling browserHistory.push() is totally fine. If it works for your use case and you don't need to know about the route changes in your reducers, carry on!
That said, the "purist" way would be for your epic to emit an action that will cause the route change. This can be done in react-router v4 by using the new react-router-redux, which supersedes the old one with the same name.
Once added, you can use the provided actions creators:
import { push } from 'react-router-redux';
export const somethingEpic = action$ =>
action$.ofType(SOMETHING)
.switchMap(() => {
somethingLikeAjaxOrWhatever()
.mergeMap(response => Observable.of(
somethingFulfilled(response),
push('/success-page')
))
});
To be clear, push() replace() etc in react-router-redux are action creators--aka action factories. They don't actually cause the route change themselves, or perform any side effects at all. They return an action that needs to be dispatched somehow for the route to change.
The other benefit of using actions to signal route change intents is testability. You no longer have to mock a history API, you can just assert that the epic emits the expected action. This is known as "effects as data", since your code doesn't perform the actual side effect, you just generate the intent.

Related

Yii2: Attach behavior to every controller

How do we attach a behavior to all web controllers in the application?
I understand this is theoretically possible with dependency injection, so I assumed something like this would work:
Yii::$container->set('yii\web\Controller', [
'as myBehavior' => [
'class' => 'app\behaviors\MyBehavior',
],
]);
however DI requires an exact class match (attaching to a parent class will not work). There is no way to know all the controller names in advance, especially when most are coming from 3rd party modules.
Is there another way to accomplish this?
EDIT: The purpose of this is to dynamically add controller filters (which are just a special type of behaviors). Therefore attaching the behavior during the EVENT_BEFORE_ACTION event is not sufficient, because it is triggered long after request filtering.
The module's (and application's) beforeAction event is triggered before the controller's version of that event. You can take advantage of that and use it to attach behaviors to current controller.
For example in your web.php config:
return [
'on beforeAction' => function() {
Yii::$app->controller->attachBehavior(
'myBehavior',
\app\behaviors\MyBehavior::class
);
},
// ... other configurations
];
Of course the disadvantage is that the behavior is not attached from the start.
NOTE: If your goal is attaching a filter to each controller, you can simply attach it to application itself instead of controllers.
Interesting problem, I must say. I could not find the simple solution for this but I have this hacky idea. You could take advantage of Yii autoloader and load your version of yii\web\Controller instead of the original one.
To do that:
Copy the original file from vendor and place it in your app
Don't change the original namespace and name.
Add your behavior config (or just the behavior's code, whatever) inside.
Add this line below in a place that will be called every time the app runs (like entry point file or bootstrap file, it must be called after vendor/yiisoft/yii2/Yii.php file is required):
Yii::$classMap['yii\web\Controller'] = ''; // replace '' with the path to your version
// of yii\web\Controller
Now, every time autoloader tries to load yii\web\Controller it will load your version instead so it should work like you want it.
The obvious con of this is that you will have to check manually if the original file has not been updated when upgrading Yii to make it up-to-date.
Child controller behavior depends on AccesControler behavior
class WorkerimgController extends OfficeController{
public function behaviors()
{
return ArrayHelper::merge(parent::behaviors(), [
]);
}
}

How to handle object freezing for redux

Regarding redux -> in development mode I would like to "freeze" the object state after the reducers have done their work and before subscribers get notified...
My approach was to define middleware for "freezing" the state of the object (e.g. with node module deep-freeze-strict).
But it seems this is not the correct approach. Because of a subscriber receives the updated state before the freezing takes place...
Does anybody has an idea how to define such freezing before the subscribers are notified??
My solution for this was to define a function which wraps the reducers:
export function freezeStateOfReducer(reducer): any {
return (state, action) => {
let newState = reducer(state, action);
freezeState(newState);
return newState;
};
}
export const rootReducer = combineReducers({
firstReducer: ...
});
createStore(freezeStateOfReducer(rootReducer));
That's an interesting question, actually. In theory, the only state updates should be happening in the reducer. In practice, I've definitely seen cases where people were accidentally mutating things in their mapState functions. You're definitely right that subscribers are notified before the middleware sees the updated state.
This might be a valid use case for a store enhancer, which could ensure that the state is frozen before actually notifying subscribers. Or, a higher-order reducer that wraps around your normal root reducer.
Also, there are several existing "freeze state in development" utilities already out there. See the DevTools#Linting section of my Redux addons catalog for a list of those existing libs.

Calling unit/functional test assertions after change events in Polymer

I've been writing some functional tests in Mocha, changing items and then checking if the changes propagated correctly. Currently, I'm using window timeouts to give Polymer time to update elements, but this feels like a hack. The developer guide outlines a few different observation hooks, but I'm not sure which one I should call.
The one that sounds the closest is a recommendation to attach an async call to a propertyChanged event. However, many items use propertyChanged, will attaching an async task to a propertyChanged event reliably call the async task after the element's methods attached to the original propertyChanged have been called?
Bonus points for information on whether the given solution is forward compatible with Polymer 1.0 (or .8/.9).
I was looking in the wrong place, the right place is the async portion of Polymer's testing how-to. The right function to use is flush(callback), which will "trigger a flush of any pending events and observations, ensuring that notification callbacks are dispatched after they have been processed."
Their documentation globs tests together, I prefer individual elements for each test-suite and each test. This is especially helpful when debugging functional tests as the changes are preserved and it's easier to setup break points:
before(function(done){
nonMatchingEl.search = "";
flush(done);
});
test('updates the "pre" property', function() {
assert.equal(nonMatchingEl.pre, 'prematch-hello-postmatchhello');
});
//test two ...

Polymer: when to use async?

What's the purpose of async method in polymer? When should I use it?
Right now I'm using it like hm-this-bug-is-kinda-weird-maybe-async-will-fix-it-yep-id-did-yey. It does not give me any confidence in my code as I'm sprinkling async just when some timing bug shows up.
The answer is slightly different here depending on whether you're using Polymer 0.5 or 1.0. In 1.0, more operations are synchronous, so you may not see quite as much need for async (also, the async method works slightly differently in 1.0).
Let's start with 0.5. Most of the cases have to do with the effects of changing properties. Properties used in data bindings or observers are observed for changes. When you change one of these
properties, any side-effects of that change take place asynchronously, with microtask timing. That means that the work happens after the current event handler returns, but before the next event is processed.
In other words, if I have a data binding like this:
<div id="output">{{someProperty}}</div>
Suppose I have the following code:
this.someProperty = "New Value";
console.log(this.$.output.textContent); // logs "Old Value"
This is where the asynchrony bites you. If you want the bound data to be updated, you need to give the data binding system a chance to work. If you move that console.log statement into an async, so it's executed at a later time, you get the response you expect:
this.async(function() {
console.log(this.$.output.textContent); // logs "New Value"
});
Most of the time, you don't need to poke at data bound DOM elements. But in the event that you do, or that you're waiting on the side effect of an observer, you probably want an async.
In Polymer 1.0, data binding and single-property observers are synchronous. Multi-property observers and some DOM operations are async.
(While the APIs are different from JavaScript, this Dart article about the event loop is the best one I've found to describe the event loop and microtask queue: https://www.dartlang.org/articles/event-loop/)

Angular - building a "public" function (newbie)

I'm After several days learning angularJS through converting my standart JS app to a ng one.
I was wondering about this simple scenario:
I have a global function called fb_connect(),
it can be used from any page (or any controller if you like) to make a facebook-based login.
This function makes a simple http call and receives a JSON object contain data to move on (display a pop up, login, etc...)
I read that I can define a Factory or a Service for my app and use it in any controller, which works fine.
So, I created a fb_connect factory function.
The problem is that now, in every page (every controller), I have to define that fb_connect in the constructor of every controller - for example :
function welcome($scope,fb_connect){});
What is the proper way to do this kind of actions using Angular without having to define these functions each and every time in every controller?
Thanks
Setting up factories and services is all part of the dependency injection system of Angular. Using that system is great when you need to create things that depend on other injected things. It's a big tree of dependencies. It's also nice for creating singletons, such that everywhere in your code end up using the same instance of some object.
It sounds to me like neither of these benefits apply in your case. I'd suggest just not using Angular's DI for it. You have some function defined globally, just call it directly and skip the DI. There's nothing wrong with that.
Of course you say it makes an Ajax call, so doesn't depend on the Angular $http service?
Your two options are:
Declare the function on the $rootScope
Inject it as a service
My advice is to go with making it a service. The whole purpose of services is explained in the Angular.js docs, just like this quote:
Angular services are singletons that carry out specific tasks common to web apps... To use an Angular service, you identify it as a dependency for the dependent (a controller, or another service) that depends on the service.
As you mentioned in your question, you'd prefer to not define the service in every controller you wish to use it in. With $rootScope you'll be injecting that also in every controller. So really it's a question of which you prefer, although to answer your question, the proper way of using a factory or service is to inject it into the controller you wish to use it in.
You can always put it in the $rootScope
myApp.run(function($rootScope, fb_connect){
$rootScope.welcome = function(){
};
});