Using ReactJS createElement to output HTML without JSX - javascript

I am trying to create this code in ReactJS without JSX
<li>
<a href="javascript:;" onClick={onClick ? this.handleClick : null}>
<div className="home-gallery" style={{background: `url(${photo})`}}/>
</a>
</li>
Reason is due to altering previous code in a component that doesn't quite fit my needs. Reading some other posts I came to this but its far from working.
_createClass(Photo, [{
key: 'handleClick',
value: function handleClick(event) {
var _props = this.props,
onClick = _props.onClick,
index = _props.index,
photo = _props.photo;
onClick(event, { photo: photo, index: index });
}
}, {
key: 'render',
value: function render() {
var _props2 = this.props,
photo = _props2.photo,
onClick = _props2.onClick,
margin = _props2.margin;
var imgStyle = { background: `url(${photo})`, margin: margin };
return
_react2.default.createElement('li', null,
_react2.default.createElement('a', _extends({
onClick: onClick ? this.handleClick : null
},
_react2.default.createElement('div', _extends({
style: onClick ? _extends({}, imgStyle, imgWithClick) : imgStyle
}))
))
)
}}]);
Could someone point me in the direction of fixing this or reference how to best learn what I am doing wrong.
UPDATE
I have no figured out the majority of my query with altering to but the background: 'url(${photo})' is still not producing, whilst the margin is.
var imgStyle = { background: `url(${photo})`, margin: margin };
return _react2.default.createElement(
"li",
null,
_react2.default.createElement(
"a",
{ href: "javascript:;", onClick: onClick ? this.handleClick : null },
_react2.default.createElement("div", { className: "home-gallery", style: onClick ? _extends({}, imgStyle) : imgStyle })
)
);

Okay, I came to the solution by using the online Babel compiler. Putting in the JSX gave an output that lead me toward the solution.
var imgStyle = { backgroundImage: 'url(' + photo.src + ')', margin: margin };
console.log(photo)
return _react2.default.createElement(
"li",
null,
_react2.default.createElement(
"a",
{ href: "javascript:;", onClick: onClick ? this.handleClick : null },
_react2.default.createElement("div", { className: "home-gallery", style: onClick ? _extends({}, imgStyle) : imgStyle })
)
);

Related

How to insert variable inside Menu tag - REACTJS

I have a .js file containing the code for a context menù component:
const ContextMenuDialog = (props) => {
// my state declaration, other const, etc...
const build_ITEMS_ContextMenu = () => {
const A = [
{
key: "0",
label: "AA123BB",
disabled: true
},
{
key: "1",
label: "Show"
},
{
key: "2",
label: "Edit"
},
{
key: "3",
label: "Save"
}
];
return A;
};
return (
<div>
{loading ? (
"Loading"
) : (
<Menu
title="Menu right click"
style={{ top: 10, left: 10 }}
onClick={my_onClick_function}
items={ build_ITEMS_ContextMenu }
/>
)}
</div>
)
}
export default ContextMenuDialog;
Just consider that I cannot simply past the code of const A directly inside the "items" element; if I do it,the code works properly. In the real life I need to build the const A with a my algorithm.
This code doesn't work, the context menù is not shown!
How can I solve this problem?
the problem is that you are not calling the function.
try this items={ build_ITEMS_ContextMenu() }

Rendering the navigation list from an array based on different label on toggle mode

I have a header component where I need to render three buttons, so every three buttons have three props. One is the class name, click handler and text.
So out of three buttons, two buttons act as a toggle button, so based on the click the text should change.
See the below code:
class App extends Component(){
state = {
navigationList: [{
text: 'Signout',
onClickHandler: this.signoutHandler,
customClassName: 'buttonStyle'
}, {
text: this.state.isStudents ? 'Students' : 'Teachers',
onClickHandler: this.viewMode,
customClassName: 'buttonStyle'
}, {
text: this.state.activeWay ? 'Active On' : 'Active Hidden',
onClickHandler: this.activeWay,
customClassName: 'buttonStyle'
}]
}
signoutHandler = () => {
// some functionality
}
viewMode = () => {
this.setState({
isStudents: !this.state.isStudents
})
}
activeWay = () => {
this.setState({
activeWay: !this.state.activeWay
})
}
render(){
return (
<Header navigationList={this.state.navigationList}/>
)
}
}
const Header = ({navigationList}) => {
return (
<>
{navigationList && navigationList.map(({text, onClickHandler, customClassName}) => {
return(
<button
onClick={onClickHandler}
className={customClassName}
>
{text}
</button>
)
})}
</>
)
}
The other way is I can pass all the props one by one and instead of an array I can write three button elements render it, but I am thinking to have an array and render using a map.
So which method is better, the problem that I am facing is if use the array. map render
the approach I need to set the initial value as a variable outside and how can I set the state.
And I am getting the onClick method is undefined, is it because the function is not attached to the state navigation list array.
Update
I declared the functions above the state so it was able to call the function.
So in JS, before the state is declared in the memory the functions should be hoisted isn't.
class App extends React.Component {
constructor(props){
super();
this.state = {
isStudents:false,
activeWay:false,
}
}
createList(){
return [{
text: 'Signout',
onClickHandler: this.signoutHandler.bind(this),
customClassName: 'buttonStyle'
}, {
text: this.state.isStudents ? 'Students' : 'Teachers',
onClickHandler: this.viewMode.bind(this),
customClassName: 'buttonStyle'
}, {
text: this.state.activeWay ? 'Active On' : 'Active Hidden',
onClickHandler: this.activeWay.bind(this),
customClassName: 'buttonStyle'
}];
}
signoutHandler(){
}
viewMode(){
this.setState({
isStudents: !this.state.isStudents
})
}
activeWay(){
this.setState({
activeWay: !this.state.activeWay
})
}
render(){
return (
<div>
<div>ddd</div>
<Header navigationList={this.createList()} />
</div>
)
}
}
const Header = ({navigationList}) => {
console.log(navigationList);
return (
<div>
{navigationList && navigationList.map(({text, onClickHandler, customClassName}) => {
return(
<button
onClick={onClickHandler}
className={customClassName}
>
{text}
</button>
)
})}
</div>
)
}
ReactDOM.render(<App />, document.querySelector("#app"))
https://jsfiddle.net/luk17/en9h1bpr/
Ok I will try to explain, If you see you are using function expressions in your class and as far as hoisting is concerned in JavaScript, functions expressions are not hoisted in JS only function declarations are hoisted, function expressions are treated as variables in JS.
Now for your case you don't have to shift your functions above the state, you can simply use constructor for initializing state as
constructor(props) {
super(props);
this.state = {
isStudents: false,
activeWay: false,
navigationList: [
{
text: "Signout",
onClickHandler: this.signoutHandler,
customClassName: "buttonStyle"
},
{
text: "Teachers",
onClickHandler: this.viewMode,
customClassName: "buttonStyle"
},
{
text: "Active Hidden",
onClickHandler: this.activeWay,
customClassName: "buttonStyle"
}
]
};
}
Now you will have your handlers available as it is
Sandbox with some modification just to show
EDIT:
You can have default text for buttons and change it when clicking,
Sandbox updated
Hope it helps

Rendering old ReactJS components with new ReactJS

I'm currently porting a very old ReactJS application to ReactJS 16 however I'm struggling on how the render function works since I don't have a React.DOM anymore.
On the old component I've got the following (I've removed unnecessary code from example):
define([
'react'
], function(
React
){
var D = React.DOM;
return React.createClass({
render: function() {
//If the Engine is not connected or the game is starting
if(this.state.engine.connectionState !== 'JOINED' || this.state.engine.gameState === 'STARTING')
return D.div({ className: 'bet-bar-starting' });
var betPercentages = calculatePlayingPercentages(this.state.engine);
var playingLostClass, cashedWonClass, mePlayingClass;
if(this.state.engine.gameState === 'ENDED') {
playingLostClass = 'bet-bar-lost';
cashedWonClass = 'bet-bar-won';
mePlayingClass = StateLib.currentlyPlaying(this.state.engine)? 'bet-bar-me-lost': 'bet-bar-me-won';
} else {
playingLostClass = 'bet-bar-playing';
cashedWonClass = 'bet-bar-cashed';
mePlayingClass = StateLib.currentlyPlaying(this.state.engine)? 'bet-bar-me-playing': 'bet-bar-me-cashed';
}
return D.div({ className: 'bet-bar-container' },
D.div({ className: cashedWonClass, style: { width: betPercentages.cashedWon + '%' } }),
D.div({ className: mePlayingClass, style: { width: betPercentages.me + '%' } }),
D.div({ className: cashedWonClass, style: { width: betPercentages.cashedWonAfter + '%' } }),
D.div({ className: playingLostClass, style: { width: betPercentages.playingLost + '%' } })
);
}
});
});
However I'm struggling to understand how to rewrite the render() function to the latest ReactJS version? I've managed to do the following, but I don't understand how to do the multidimensional calls to the DOM.
class BetBar extends React.Component {
render() {
if(this.state.engine.connectionState !== 'JOINED' || this.state.engine.gameState === 'STARTING')
return (<div class='bet-bar-starting'/>);
let betPercentages = calculatePlayingPercentages(this.state.engine);
let playingLostClass, cashedWonClass, mePlayingClass;
if(this.state.engine.gameState === 'ENDED') {
playingLostClass = 'bet-bar-lost';
cashedWonClass = 'bet-bar-won';
mePlayingClass = StateLib.currentlyPlaying(this.state.engine)? 'bet-bar-me-lost': 'bet-bar-me-won';
} else {
playingLostClass = 'bet-bar-playing';
cashedWonClass = 'bet-bar-cashed';
mePlayingClass = StateLib.currentlyPlaying(this.state.engine)? 'bet-bar-me-playing': 'bet-bar-me-cashed';
}
//I don't understand how to do the D.div functions...
}
}
ReactDOM.render(<BetBar />);
The code you are looking at is from before JSX. JSX introduced a syntax which allows you to create elements without calling functions. This results in a much more declarative style, similar to HTML, which allow you to describe your components.
To translate old code -- pre JSX -- to modern day React, all you need to do is understand the function call.
D.div({ className: 'bet-bar-container' })
This creates a div with the className "bet-bar-container", in React is takes the HTML attributes as arguments and applies them to the desired DOM element for you.
<div className="bet-bar-container"></div>
So, for example with the code you have, it would roughly translate to something like this:
<div className="bet-bar-container">
<div className="cashedWonClass", style={{ width: betPercentages.cashedWon + '%' }}></div>
<div className="mePlayingClass", style={{ width: betPercentages.me + '%' }}></div>
<div className="cashedWonClass", style={{ width: betPercentages.cashedWonAfter + '%' }}></div>
<div className="playingLostClass", style={{ width: betPercentages.playingLost + '%' }}></div>
</div>

How to add click event with React createElement

Following is the code that I'm using to create an HTML tag. I want to add a click event on this. How can I add this?
let elem = React.createElement(
this.props.tag,
{
style: this.props.style,
id: this.props.id
onClick: ()
},
[this.props.text]
)
If you are creating an HTML tag, you simply need to pass on the onClick as a function to the element as props. With React.createElement you can write it like
let elem = React.createElement(
this.props.tag,
{
style: this.props.style,
id: this.props.id
onClick: () => {console.log('clicked')}
},
[this.props.text]
)
You could also pass a predefined function like below
let elem = React.createElement(
this.props.tag,
{
style: this.props.style,
id: this.props.id
onClick: this.handleClick.bind(this)
},
[this.props.text]
)

React: how to work with the database?

I'm studying react.js.
How to correctly add class 'use' to the element where the click occurs? From other elements it needs to be removed.
How to get rid of the index, but be able to handle and dispose of the items?
var DB = [
{
name: 'Имя 1', url: 'http://localhost:1', use: true
},
{
name: 'Имя 2', url: 'http://localhost:2', use: false
},
{
name: 'Имя 3', url: 'http://localhost:3', use: false
}
];
class SideBarEl extends React.Component {
hoverLi(t){
if(t.target.id !== ''){
for (var i = 0; i < DB.length; i++){
if(t.target.id == i){
DB[i].use = true;
} else {
DB[i].use = false;
}
}
}
}
render(){
var newsTemplate = DB.map(function(item, index) {
return (
<li key={ index } id={ index } onClick={ this.hoverLi.bind(this)} className={ item.use ? 'use' : '' }>
{ item.name }
<span>
{ item.url }
</span>
</li>
)
}, this);
return(
<ul>{newsTemplate}</ul>
)
}
}
1 Set this.state
You need to use React state to handle such things and rerender when action occurs. If you just use a variable, React doesn't know when something should be rerendered.
this.state = {
links: [
{
name: "Имя 1",
url: "http://localhost:1",
use: true
},
{
name: "Имя 2",
url: "http://localhost:2",
use: false
},
{
name: "Имя 3",
url: "http://localhost:3",
use: false
}
]
};
Read more about state on https://facebook.github.io/react/docs/state-and-lifecycle.html
2 Update state by using onClick
handleClick(item) {
this.setState(prevState => ({
links: prevState.links.map(link => {
link.use = link === item;
return link;
})
}));
}
render() {
// rest of code...
<li
key={item.url}
id={index}
onClick={() => this.handleClick(item)}
className={item.use ? "use" : ""}
>
// rest of code...
}
For only 3 links it's okay to have such non-optimized code. If you would like to apply this for big collection of links (hundreds or thousands of links), it will require a bit more work but probably it's out of you question's scope.
3 Demo
https://codesandbox.io/s/mQoomVOmA
If you click on a link, it will be red and rest will be black because I added this small CSS .use { color: red; }
Have fun and happy coding.

Categories