Am newbie to ReactJS. I want to use a IF block inside the render function. While search for this I got result like "You should use ternary operator instead of IF statement". But if I want to use something like,
$.each(array, function(i, x) {
var flag = 0
if({x.a1} || !{x.a2}) {
flag = 1;
<p>true flag enabled</p>
}
<p>...</p>
});
How to convert this statement into JSX syntax or how to use it in React render fucntion.
Thanks in advance.
This link will help you
https://facebook.github.io/react/tips/if-else-in-JSX.html
But I'd use something like this, as its slightly easier to read (IMHO). Note, your array is a prop - passed into the component (or could be a state). I'd use lodash for mapping etc, cause its so useful all over the place (https://lodash.com/)
_renderElements: function(){
return _.map(this.props.array, function(el){
var flag = 0;
return el.a1 || el.a2 ? <p>{'true 1 enabled'}</p> : <p>...</p>;
})
},
render: function () {
return (
{this._renderElements()}
}
);
}
Hope that's helpful.
I do this in one of two ways, depending mostly on how big the if statement is.
one scenario, I don't know if I'm going to render an element or not:
Component = React.createClass({
render() {
var elem;
if (something) {
elem = (<SomeOtherComponent />);
}
return (
<div>{elem}</div>
);
}
});
This is basically a way to either show the element/component or not. If I'm going to map something I would use a separate method and call it:
Component = React.createClass({
mapIt() {
return this.props.items.map(item => {
... do your stuff ...
return (
<SomeOtherComponent prop1={item.value} ... />
);
});
},
render() {
return (
{this.mapIt()}
);
}
});
This to me is a nice clean way of handling.
You want to have your render function look something like this:
render: function () {
return (
{
array.map(function (el, i) {
var flag = 0;
if (el.a1 || el.a2) {
flag = 1;
return <p>true flag enabled</p>;
} else {
return <p>...</p>;
}
}
}
);
}
React allows you to return an array of React elements, so you can map your array and return a JSX element for every element of the array.
Related
I want to create a function that takes a string that might be :
"triangle" , "square", or "rectangle"
And according to this argument, I want to return a pointer on a class Form.
I have a mother class "Form", who inherits of "Class Rectangle", "Class Square", and "Class Rectangle"
But I don't want to do :
if (name == "rectangle")
return (new Rectangle());
else if (name == "square")
return (new Square());
... etc
I thought about pointers on functions, but I wanted the simplest method and clean code, what do you recommand ?
Thank's !
Yes, you could use function pointers or lambdas. You can use a map of strings to functors:
std::map<std::string, std::function<ShapeBase*()>> actions = {
{ "rectangle", []{return new Rectangle;} },
{ "square", []{return new Square;} }
};
return actions[name]();
But if you're not going to change the actions at run time, it's hard to beat what you had really.
In a comment you asked "Imagine it had 500 forms". Indeed, the map lookup will be faster than 500 chained if statements. You could make it a switch with some effort: use hashes for the names instead of the strings themselves. If the hash function is constexpr you can write that easily:
switch (hash(name)) {
case hash("rectangle"): return new Rectangle;
case hash("square"): return new Square;
// 500 cases
}
The switch statement will be optimized to do a binary search or something like that, on the integer hash values. You'll also get a compile-time error if there is a hash clash.
You can use std::unordered_map:
using FormPtr = std::unique_ptr<Form>;
using Creators = std::unordered_map<std::string,std::function<FormPtr()>>;
FormPtr create( const std::string &name )
{
const static Creators creators {
{ "triangle", [] { return std::make_unique<Triangle>(); } },
{ "square", [] { return std::make_unique<Square>(); } },
{ "rectangle", [] { return std::make_unique<Rectangle>(); } }
};
auto f = creators.find( name );
if( f == creators.end() ) {
// error handling here
}
return f->second();
}
If you need to add creators outside you can put them into a class and allow them to update the map and register more creators dynamically.
I have several functions that try and evaluate some data. Each function returns a 1 if it can successfully evaluate the data or 0 if it can not. The functions are called one after the other but execution should stop if one returns a value of 1.
Example functions look like so:
int function1(std::string &data)
{
// do something
if (success)
{
return 1;
}
return 0;
}
int function2(std::string &data)
{
// do something
if (success)
{
return 1;
}
return 0;
}
... more functions ...
How would be the clearest way to organise this flow? I know I can use if statements as such:
void doSomething(void)
{
if (function1(data))
{
return;
}
if (function2(data))
{
return;
}
... more if's ...
}
But this seems long winded and has a huge number of if's that need typing. Another choice I thought of is to call the next function from the return 0 of the function like so
int function1(std::string &data)
{
// do something
if (success)
{
return 1;
}
return function2(data);
}
int function2(std::string &data)
{
// do something
if (success)
{
return 1;
}
return function3(data);
}
... more functions ...
Making calling cleaner because you only need to call function1() to evaluate as far as you need to but seems to make the code harder to maintain. If another check need to be inserted into the middle of the flow, or the order of the calls changes, then all of the functions after the new one will need to be changed to account for it.
Am I missing some smart clear c++ way of achieving this kind of program flow or is one of these methods best. I am leaning towards the if method at the moment but I feel like I am missing something.
void doSomething() {
function1(data) || function2(data) /* || ... more function calls ... */;
}
Logical-or || operator happens to have the properties you need - evaluated left to right and stops as soon as one operand is true.
I think you can make a vector of lambdas where each lambdas contains specific process on how you evaluate your data. Something like this.
std::vector<std::function<bool(std::string&)> listCheckers;
listCheckers.push_back([](std::string& p_data) -> bool { return function1(p_data); });
listCheckers.push_back([](std::string& p_data) -> bool { return function2(p_data); });
listCheckers.push_back([](std::string& p_data) -> bool { return function3(p_data); });
//...and so on...
//-----------------------------
std::string theData = "Hello I'm a Data";
//evaluate all data
bool bSuccess = false;
for(fnChecker : listCheckers){
if(fnChecker(theData)) {
bSuccess = true;
break;
}
}
if(bSuccess ) { cout << "A function has evaluated the data successfully." << endl; }
You can modify the list however you like at runtime by: external objects, config settings from file, etc...
So I have function that looks like this
task<shared_ptr<myObjectsResult>> task1 = create_task([this,token, stream]
{
// Here I have code that is working, but I would like to refactor it
// maybe even make it go after or before this surrounding task.
create_task(BitmapDecoder::CreateAsync(stream)).then([this, token]
(BitmapDecoder^ bitmapDecoder)
{
create_task(bitmapDecoder->GetSoftwareBitmapAsync()).then([this, token]
(SoftwareBitmap^ softwareBitmap)
{
OcrEngine^ ocrEngine = OcrEngine::TryCreateFromUserProfileLanguages();
if (ocrEngine != nullptr)
{
create_task(ocrEngine->RecognizeAsync(softwareBitmap)).then([fileInfo, this, transactionPriority, token]
(OcrResult^ ocrResult)
{
doSomethingWithText(OcrResult->Text->Data());
});
}
});
});
...
return runAsyncFunctionThatReturnsMyObjectResultTask(token);
});
It works and all is great, but I want to move OCR logic to some other part of code not in here, but I would love to call it from here.
What I have tried is creating
task<OcrResult^> GetOCRTextFromStream(_In_ IRandomAccessStream^ stream)
{
create_task(BitmapDecoder::CreateAsync(stream)).then([]
(BitmapDecoder^ bitmapDecoder)
{
create_task(bitmapDecoder->GetSoftwareBitmapAsync()).then([]
(SoftwareBitmap^ softwareBitmap)
{
OcrEngine^ ocrEngine = OcrEngine::TryCreateFromUserProfileLanguages();
if (ocrEngine != nullptr)
{
return create_task(ocrEngine->RecognizeAsync(softwareBitmap));
}
else
{
OcrResult^ ocrResult = nullptr;
return concurrency::task_from_result(ocrResult);
}
}
}
and then call this.
GetOCRTextFromStream(stream).then([this, token]
(OcrResult^ ocrResult)
{
doSomethingWithText(OcrResult->Text->Data());
}
Ofcourse this does not work, but you get what I want, I just want to refactor this, and I just cannot understand how to do what I want, and if it is doable (I guess it is?)
Thanks all and sorry if my question is nooby :)
This is C++/CX, and solution is to put return.
This should work if you just add return in front of two create_task that you have
return create_task([]
{
return create_task([]
{
...
}
}
I have left/right arrows on a page and I want to pick the animation without having to define a relationship between all the routes. Is it possible to set it on the {{link-to}}? Right now it's pretty brittle.
I have been looking, and I don't think it's possible to know what link was clicked from the transition it caused. However, I can think of two different ways to tackle your use case.
Solution 1: metaprogramming
Make a list of your routes and generate transitions dynamically from it. Something like this:
// app/transitions.js
export default function() {
const orderedRoutes = [
'left-route',
'center-route',
'right-route',
];
// See https://github.com/coleww/each-cons
// where I pinched this from
function eachCons(a, n) {
var r = []
for (var i = 0; i < a.length - n + 1; i++) {
r.push(range(a, i, n))
}
return r
}
function range (a, i, n) {
var r = []
for (var j = 0; j < n; j++) {
r.push(a[i + j])
}
return r
}
eachCons(orderedRoutes, 2).forEach(pair => {
// `pair` will be each pair of consecutive routes
// on our `orderedRoutes` list
const left = pair[0];
const right = pair[1];
// For each pair, define a transition
this.transition(
this.fromRoute(left),
this.toRoute(right),
this.use('toLeft'),
this.reverse('toRight')
);
});
}
Note that I only define transitions for adjacent routes. If you want to define a transition between left-route and center-route, you'll need to alter the algorithm to define new combinations.
Solution 2: callback to fromRoute
The function fromRoute can not only take a string, but also a function. This function receives two parameters: the names of the initial and the final routes of a transition. In this function you can return true if the transition should apply, and false otherwise. See here:
http://ember-animation.github.io/liquid-fire/#/transition-map/route-constraints
You can use this function to decide whether you should be going left or right (as per your use case). See this:
// app/transitions.js
export default function() {
// Names of the routes in the left-right succession
const orderedRoutes = [
'left-route',
'center-route',
'right-route',
];
function isLeft(initial, destination) {
const i0 = orderedRoutes.indexOf(initial);
const i1 = orderedRoutes.indexOf(destination);
if (i0 === -1 || i1 === -1) {
// This is not one of the transitions
// in the left-right succession
return false;
}
if (i0 === i1) {
// They are the same route
return false;
}
// This will be `true` if the initial route
// is "to the left" of the destination route
return i0 < i1;
}
this.transition(
this.fromRoute(isLeft),
this.use('toLeft')
this.reverse('toRight')
);
}
In this example, for each transition we check the initial and the destination route. We see if they belong to the left-right succession, and whether the transition corresponds to a "left" or a "right". If it's a "left" we return true in the "toLeft" case. If it's a "right", we return true in the "toRight" case.
I recently upgraded my ember version from 1.5 to 1.7. Everything is working fine, expect for when I run my tests I get this annoying warning message :
DEPRECATION: Do not use `.then` on an instance of Ember.Application. Please use the `.ready` hook instead.
I am using mocha adapter, but I don't think its anyhow related to the adapter because when I created a simple jsbin using this adapter I did not get any messages. This message shows up when ever in my test I use andThen(function(){ .... }). The call that causes this warning message originates from this function:
//IN ember.js file
function wait(app, value) {
return Test.promise(function(resolve) {
// If this is the first async promise, kick off the async test
if (++countAsync === 1) {
Test.adapter.asyncStart();
}
// Every 10ms, poll for the async thing to have finished
var watcher = setInterval(function() {
// 1. If the router is loading, keep polling
var routerIsLoading = !!app.__container__.lookup('router:main').router.activeTransition;
if (routerIsLoading) { return; }
// 2. If there are pending Ajax requests, keep polling
if (Test.pendingAjaxRequests) { return; }
// 3. If there are scheduled timers or we are inside of a run loop, keep polling
if (run.hasScheduledTimers() || run.currentRunLoop) { return; }
if (Test.waiters && Test.waiters.any(function(waiter) {
var context = waiter[0];
var callback = waiter[1];
return !callback.call(context);
})) { return; }
// Stop polling
clearInterval(watcher);
// If this is the last async promise, end the async test
if (--countAsync === 0) {
Test.adapter.asyncEnd();
}
// Synchronously resolve the promise
run(null, resolve, value);//THIS CAUSES THE WARNING MESSAGE
}, 10);
});
}
and then ends up here which finally gives the warning:
//IN ember.js file
__exports__.inspect = inspect;// The following functions are intentionally minified to keep the functions
// below Chrome's function body size inlining limit of 600 chars.
function apply(t /* target */, m /* method */, a /* args */) {
var l = a && a.length;
if (!a || !l) { return m.call(t); }
switch (l) {
case 1: return m.call(t, a[0]);
case 2: return m.call(t, a[0], a[1]);//this is executed with a[0] as a function that seems like a promise
case 3: return m.call(t, a[0], a[1], a[2]);
case 4: return m.call(t, a[0], a[1], a[2], a[3]);
case 5: return m.call(t, a[0], a[1], a[2], a[3], a[4]);
default: return m.apply(t, a);
}
}
the function that is passed as an argument to case 2 is :
function (value) {
if (sealed) { return; }
sealed = true;
if (thenable !== value) {
resolve(promise, value);
} else {
fulfill(promise, value);
}
}
Any idea how I am avoid getting this warning message. thanks.
UPDATE :
I think I found atleast one of the reasons for this issue which was caused by the registerAsyncHelper. We have a helper written as :
Ember.Test.registerAsyncHelper('clickCheckbox', function(app, selector, context) {
var $el = findWithAssert(selector, context);
Ember.run($el, 'mousedown');
Ember.run($el, 'mouseup');
Ember.run($el, 'click');
// Workaround for IE8 because programmatically clicking a checkbox
// does not fire the "change" event
Ember.run($el, 'change');
return wait(app);
});
so if I don't use this helper, the issue seems to disappear! Also if I were to do return wait() instead of wait(app), things work.