I am converting an existing application into ReactJS. I have found something difficult to do well in ReactJS. Below is what I would like to do
render () {
return (<div id="container">
<div className="shared">shared content here</div>
<div className="shared">shared content here</div>
<div className="shared">shared content here</div>
{featureAEnabled ?
(<div className="featureA">featureA enabled content</div>
<div className="featureA">featureA enabled content</div>) :
(<div className="old">featureA disabled content</div>
<div className="old">featureA disabled content</div>)
</div>);
}
The issue is you cannot return multiple elements in React, you must always return a single element.
My current solutions involve
Rewrite all my css to allow for elements to encapsolate any of these feature switches
Do the following:
code:
render() {
return (<div id="container">
<div className="shared">shared content here</div>
<div className="shared">shared content here</div>
<div className="shared">shared content here</div>
{featureAEnabled && <div className="featureA">featureA enabled content</div>}
{featureAEnabled && <div className="featureA">featureA enabled content</div>}
{!featureAEnabled && <div className="old">featureA disabled content</div>}
{!featureAEnabled && <div className="old">featureA disabled content</div>}
</div>);
}
Is there a way to allow for codeblocks that are based on a condition and render multiple elements like in my first code snippet?
Ideally you should try to separate 'featureAEnabled' and 'featureADisabled' elements in separate components and then render them.
Other way of doing that is to have your 'featureAEnabled' and 'featureADisabled' elements in an array and return it. Like below:
render() {
let renderFeatureA = [
<div >featureA enabled content</div>,
<div >featureA enabled content</div>
];
let disableFeatureA = [
<div >featureA disabled content</div>,
<div >featureA disabled content</div>
];
let renderItems = featureAEnabled ? renderFeatureA : disableFeatureA;
return (
<div id="container">
<div >shared content here</div>
<div >shared content here</div>
<div >shared content here</div>
{renderItems}
</div>
)
};
One way to do this is to just toggle a class in your render.
let featureEnabledClasses = 'hidden';
if (myCondition === true) {
featureEnabledClasses = '';
}
Then you can just serve up
<div className={featureEnabledClasses}>featureA enabled content</div>
Related
My function renderTitles is supposed to output many bootstrap cards with title from an array that i got from an API. I have tested before and the array is there and all its data. The problem is when i call renderTitles function it does not output anything.
I have tried many map function examples and none have worked
renderTitles = () => {
return this.state.popularMovies.map(t => {
return (
<div class="container">
<div class="card" style={{ width: "12rem" }}>
<div class="card-body">
<img
class="card-img-top"
src="http://image.tmdb.org/t/p/w342/iflq7ZJfso6WC7gk9l1tD3unWK.jpg"
/>
<h5 class="card-title">t.title</h5>
</div>
</div>
</div>
);
});
};
It is expected to output all titles inside bootstrap cards with one title each.
Try wrapping the data that you want to print in {} for example:
<h5 class="card-title">
{t.title}
</h5>
Also: when you call your renderTitles function, make sure that is wrapped in {} as well:
<div class="all-my-titles">
{this.renderTitles()}
</div>
Try this if it helps
renderTitles = () =>{
return this.state.popularMovies.map((t)=>(
<div class="container">
<div class="card" style={{width: '12rem'}}>
<div class="card-body">
<img class="card-img-top" src="http://image.tmdb.org/t/p/w342/iflq7ZJfso6WC7gk9l1tD3unWK.jpg"/>
<h5 class="card-title">
{t.title}
</h5>
</div>
</div>
</div>
))
}
You need to use wrap both output of renderTitles and t.title in {}.
Reference
I'm pretty new to react and I had a question. I have some code that populates some tabs with some info and I wanted some help creating a function that can be reused multiple times instead of reusing the same code for each tab.
<div className="box box-default">
<div className="box-header with-border">
<h3 className="box-title">Strings Info</h3>
<div className="key-details">
<dl className="dl-horizontal">
<dt>Count</dt>
<dd>{count}</dd>
<dt>Average Length</dt>
<dd>{avg_length}</dd>
</dl>
</div>
</div>
<div className="box-header with-border">
<h3 className="box-title">Strings</h3>
<div>
<pre>
{this.props.raw_strings}
</pre>
</div>
</div>
</div>
I was thinking I could create a populateTabs function that can take the count, average length, and the raw string data from the props as a parameter. The count, avg_length, and raw_strings are different for each tab as they each represent a different string type so I've been reusing this block for every tab despite only changing the 3 variables. What is the best way to cut down on the code reuse in this situation? thanks!
The code can be extracted to a component. In case some parameters are common in some cases, it can be higher-order component that accepts common parameters:
const boxHOC = (count, avg_length) => props => (
<div className="box box-default">
<div className="box-header with-border">
<h3 className="box-title">Strings Info</h3>
<div className="key-details">
<dl className="dl-horizontal">
<dt>Count</dt>
<dd>{count}</dd>
<dt>Average Length</dt>
<dd>{avg_length}</dd>
</dl>
</div>
</div>
<div className="box-header with-border">
<h3 className="box-title">Strings</h3>
<div>
<pre>
{props.raw_strings}
</pre>
</div>
</div>
</div>
);
const OneTwoBox = boxHOC(1, 2);
const ThreeFourBox = boxHOC(3, 4);
React is all about components, so rather than a normal function, you're better off extracting the common markup into a component, which can actually be a "function component" (as opposed to a "class component").
export function PopulateTab({ avgLength, count, rawStrings }) {
return (<div className="box box-default">
<div className="box-header with-border">
<h3 className="box-title">Strings Info</h3>
<div className="key-details">
<dl className="dl-horizontal">
<dt>Count</dt>
<dd>{count}</dd>
<dt>Average Length</dt>
<dd>{avgLength}</dd>
</dl>
</div>
</div>
<div className="box-header with-border">
<h3 className="box-title">Strings</h3>
<div>
<pre>
{rawStrings}
</pre>
</div>
</div>
</div>);
}
if tabsContents is an array of objects like..
const tabsContents = [
{ avgLength: 5, count: 8, rawStrings: "foo" },
{ avgLength: 6, count: 12, rawStrings: "bar" },
];
you can use PopulateTab like so..
import { PopulateTab } from "./populate-tab";
function Tabs({ tabsContents }) {
return (
<div>
{tabsContents.map(
({ avgLength, count, rawStrings }) =>
<PopulateTab avgLength={avgLength} count={count} rawStrings={rawStrings} />
)}
</div>
);
}
or, more concisely..
function Tabs({ tabsContents }) {
return (<div>{tabsContents.map(props => <PopulateTab {...props} />)}</div>);
}
I am fetching a JSON file and trying to render the data from it. Everything shows up great when I console.log it but the JSX is not being rendered to the page. I was using forEach and read that it should be map instead but that doesn't fix my problem. Here's my code:
getPromoDetails(data) {
data = this.state.data;
Object.keys(data || {}).map(function(key) {
console.log("Promo ID: ",data[key].cm_ID)
console.log("Title: ",data[key].cm_title)
console.log("State: ",data[key].state)
console.log("Status: ",data[key].status)
console.log("Last Modified on: ",data[key].cm_lastmodified)
return
<div className="col-xs-12">
<div className="col-xs-3">
<img src={`https://link.com/thumbnail_${data[key].cm_ID}.jpg`}/>
</div>
<div className="col-xs-9">
<span className="col-xs-12"> {data[key].cm_title}</span>
<span>On: {data[key].cm_on}</span>
<span>State: {data[key].state}</span>
<span>Status: {data[key].status}</span>
<span>Last Modified: {data[key].cm_lastmodified}</span>
</div>
</div>
});
}
Any advice??
You are not returning the array that is the result of the map. You also have to make sure the JSX is on the same line as the return statement, or undefined will be returned.
getPromoDetails() {
const { data } = this.state;
return Object.keys(data || {}).map(function(key) {
return (
<div className="col-xs-12" key={key}>
<div className="col-xs-3">
<img src={`https://link.com/thumbnail_${data[key].cm_ID}.jpg`} />
</div>
<div className="col-xs-9">
<span className="col-xs-12"> {data[key].cm_title}</span>
<span>On: {data[key].cm_on}</span>
<span>State: {data[key].state}</span>
<span>Status: {data[key].status}</span>
<span>Last Modified: {data[key].cm_lastmodified}</span>
</div>
</div>
);
});
}
I have created three layouts with flex=44,flex=20 and flex=44.
Basically 3 columns on the page.
<div flex="44">
</div>
<div flex="20" class="rightcol">
</div>
<div flex="44" class="rightcol">
<div class="" ui-view>
</div>
</div>
I want to change the flex value or infact merge two flex and make it as one.
Is it possible to achieve from the controllers?
You need to keep the flex-value in the scope of the controller:
app.controller("MyCtrl", function ($scope) {
$scope.flex1 = function () { return 44; };
$scope.flex2 = function () { return 20; };
$scope.flex3 = function () { return 44; };
$scope.showFlex = function (n) {
// your condition whether the flex-ed div should be shown goes in here
return true;
}
});
Your HTML should look like this:
<div ng-controller="MyCtrl">
<div flex="{{flex1()}}" ng-if="showFlex(1)">
</div>
<div flex="{{flex2()}}" ng-if="showFlex(2)" class="rightcol">
</div>
<div flex="{{flex3()}}" ng-if="showFlex(3)" class="rightcol">
<div class="" ui-view>
</div>
</div>
</div>
I am using Foundation library.
I want to center a div in ReactJS and I am unable to achieve it.
This is a working example in plain vanilla : http://codepen.io/anon/pen/PqdzZR
<div class="vertical grid-block">
<div class="grid-block text-center"><span>Hi there !</span></div>
<div class="grid-block text-center">
<a class="button" href="#">Test Button</a>
</div>
But, this does not work with ReactJS :
var React = require('react');
var Comp = React.createClass({
render: function() {
return (<div className="grid-frame">
<div className="vertical grid-block">
<div className="grid-block text-center"><span>Instructions to login</span></div>
<div className="grid-block text-center">
<a className="button" href="#">Login with Facebook</a>
</div>
</div>
</div>);
}
});
module.exports = Comp;
In the above component, the button has the styling indicating that the Foundation css styling is working.But the div is not centered for some reason.
So, the question is how do I center a div in a ReactJS component using the Foundation library ?
return (<div class="grid-frame">
Should be className?
Check my fiddle: https://jsfiddle.net/reactjs/69z2wepo/
Maybe you forgot to add normalize.css?
var Hello = React.createClass({
render: function() {
return (<div className="grid-frame">
<div className="vertical grid-block">
<div className="grid-block text-center"><span>Instructions to login</span></div>
<div className="grid-block text-center">
<a className="button" href="#">Login with Facebook</a>
</div>
</div>
</div>);
}
});
React.render(<Hello name="World" />, document.getElementById('container'));
Not sure if React is changing the display property for the button?
Display inline-block can be horizontally centered with text align center. Display block works with margin: 0 auto;