Automatic parenthesis visual studio code (reactjs) - javascript

Does different programs behave differently regarding adding automatically parenthesis, even if i dont want to put it, im beginner on reactjs and coding in two different places on visual studio code and https://codesandbox.io, I have a code where it displays three tags (list) the same code on codesandbox has not any error message and work without any problem but on visual studio code( i have disabled all extensions) it automatically adds parenthesis and even if i delete it, it saves it with parenthesis, how to save on visual studio code without it adding automatically parenthesis: here is the code
import React, { Component } from "react";
class Counter extends Component {
state = {
count: 0,
tags: ["tag1", "tag2", "tag3"]
};
renderTags() {
if (this.state.tags.length === 0) return <p> There are no tags!</p>;
return <ul>{this.state.tags.map(tag => <li key={tag}>{tag} </li>)}</ul>;
}
render() {
return <div>{this.renderTags()}</div>;
}
}
export default Counter;
English is not my mother language so sorry for mistakes, here is how it changed my code :
renderTags() {
if (this.state.tags.length === 0) return <p> There are no tags!</p>;
return (
<ul>
{this.state.tags.map(tag => (
<li key={tag}>{tag} </li>
))}
</ul>
);
}

Related

Using Javascript to create html custom Tag

class Headers extends React.Component {
render() {
const selected = this.props.selectedPane;
const headers = this.props.panes.map((pane, index) => {
const title = pane.title;
const klass = index === selected ? 'active' : '';
return (
<li
key={index}
className={klass}
onClick={() => this.props.onTabChosen(index)}>
{title}{' '}
</li>
);
});
return (
<ul className='tab-header'>
{headers}
</ul>
);
}
}
export default class Tabs extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedPane: 0
};
this.selectTab = this.selectTab.bind(this);
}
selectTab(num) {
this.setState({selectedPane: num});
}
render() {
const pane = this.props.panes[this.state.selectedPane];
return (
<div>
<h1>Tabs</h1>
<div className='tabs'>
<Headers
selectedPane={this.state.selectedPane}
//onTabChosen={this.selectTab}
panes={this.props.panes}>
</Headers>
<div className='tab-content'>
<article>
hellooooo
{pane.content}
</article>
</div>
</div>
</div>
);
}
}
I'm currently creating a 3 tab section where if you click on a tab, it gives you a new pane.
When looking at the render function I see a custom tag called Headers.
I know it coming from the Headers class at the beginning, but how does that format work? Is that a custom tag we building?
Also when looking at its properties such as onTabChosen, when it is deleted in the render method (for learning purposes) and I click on a selected tab, an error comes up saying
"_this.props.onTabChosen is not a function".
this.props.onTabChosen(index).. was written in the Headers class but not as a function correct?
I guess because I am also confused on how this.props.onTabChosen(index) works since onTabChosen was never declared anywhere, just input after props.
When looking at the render function I see a custom tag called "Headers".
That is not a custom tag. That is a React Component.
I know it coming from the Headers class at the beginning, but how does that format work?
Headers is either a function or a class (i.e. a constructor function).
The function will be called and the first argument passed to it will be an object with properties and values that match the props on the JSX element.
If you're going to use React then read a tutorial, this is very introductory level stuff for the framework.
It is covered very early on in both the MDN tutorial and the official React tutorial.
I guess because I am also confused on how this.props.onTabChosen(index) works since onTabChosen was never declared anywhere, just input after props.
It was declared, just not in the piece of code you shared.

React JS | Render Multiple Elements

I am trying to create a email in React using the MJML email library. It runs off react and I have it all working but I need to render 2 sections rather than 1. When I render 1 it doesn't appear properly on the webpage as I need them to be different sizes.
When I try and wrap the elements within a array the return become null, take out one of the sections and it gets returned.
Any help would be appreciated, here is the code.
render() {
const { mjAttribute } = this.props
const content = [this.renderEmailOverhead()]
const innerContent = [this.renderEmailBanner(), this.renderEmailTitle(), this.renderEmailText(), this.renderEmailDivider]
return ([
<Section full-width='full-width' padding-top="0">
{ content }
</Section>,
<Section>
{ innerContent }
</Section>
])
}
Well, render method of a component can only return one element. so you'll have to wrap it in a divas Zargold mentioned.
Note that MJML component are more than a standard React component.
It has some internal logic not available in a React context. IMO you should generate MJML as standard HTML element and render it with a renderToStaticMarkup then pass it to mjml2html function as a string and mjml will compiles
return (
<mjml>
<mj-body>
<mj-container>
... // your sections goes here
</mj-container>
</mj-body>
</mjml>
)
Note that I don't think React is the best suited for this kind of work, I would recommend you to use a templating language such as mustache/handlebars which fit better.
You cannot use JSX interspersed with JavaScript like that... you could either do (you must have only one parent/root element).
<div>
<Section full-width='full-width' padding-top="0">
{ content }
</Section>
<Section>
{ innerContent }
</Section>
</div>
Or You could if you insist on using an array for some reason:
renderSection(content, fullWidth){
return (
<Section
full-width={fullWidth ? 'full-width' : false}
style={{paddingTop: fullWidth ? 0 : 'auto'}}
>
{content}
</Section>
)
}
render(){
let contents = [content, innerContent]
return(
<div>
{contents.map(section, i => renderSection(section, i % 2 === 0))
</div>
)

React updating DOM in an unpredictable manner with setState and class names

I'm attempting to do an animation with React and CSS classes. I have created a live demo, if you visit it and click the Start button you will see the text fade in and up one by one. This is the desired animation that I am after.
However, there seems to be issues of consistency when you hit Start multiple times and I cannot pinpoint why.
The Issue: Below is a recording of the issue, you can see the number 1 is not behaving as expected.
live demo
The process: Clicking Start will cancel any previous requestAnimationFrame' and will reset the state to it's initial form. It then calls the showSegments() function with a clean state that has no classNames attached to it.
This function then maps through the state adding a isActive to each segment in the state. We then render out the dom with a map and apply the new state.
This should create a smooth segmented animation as each class gets dropped one by one. However when i test this in Chrome (Version 56.0.2924.87 (64-bit)) and also on iOS, it is very inconsistent, sometimes it works perfectly, other times the first DOM element won't animate, it will just stay in up and visible it's completed transitioned state with "isActive".
I tried to replicate this issue in safari but it worked perfectly fine, I'm quite new to react so i am not sure if this is the best way to go about things, hopefully someone can offer some insight as to why this is behaving quite erratic!
/* MotionText.js */
import React, { Component } from 'react';
import shortid from 'shortid';
class MotionText extends Component {
constructor(props) {
super(props);
this.showSegments = this.showSegments.bind(this);
this.handleClickStart = this.handleClickStart.bind(this);
this.handleClickStop = this.handleClickStop.bind(this);
this.initialState = () => { return {
curIndex: 0,
textSegments: [
...'123456789123456789123456789123456789'
].map(segment => ({
segment,
id: shortid.generate(),
className: null
}))
}};
this.state = this.initialState();
}
handleClickStop() {
cancelAnimationFrame(this.rafId);
}
handleClickStart(){
cancelAnimationFrame(this.rafId);
this.setState(this.initialState(), () => {
this.rafId = requestAnimationFrame(this.showSegments);
});
}
showSegments() {
this.rafId = requestAnimationFrame(this.showSegments);
const newState = Object.assign({}, this.state);
newState.textSegments[this.state.curIndex].className = 'isActive';
this.setState(
{
...newState,
curIndex: this.state.curIndex + 1
},
() => {
if (this.state.curIndex >= this.state.textSegments.length) {
cancelAnimationFrame(this.rafId);
}
}
);
}
render(){
const innerTree = this.state.textSegments.map((obj, key) => (
<span key={obj.id} className={obj.className}>{obj.segment}</span>
));
return (
<div>
<button onClick={this.handleClickStart}>Start</button>
<button onClick={this.handleClickStop}>Stop</button>
<hr />
<div className="MotionText">{innerTree}..</div>
</div>
)
}
}
export default MotionText;
Thank you for your time, If there any questions please ask
WebpackBin Demo
Changing the method to something like this works
render(){
let d = new Date();
const innerTree = this.state.textSegments.map((obj, key) => (
<span key={d.getMilliseconds() + obj.id} className={obj.className}>{obj.segment}</span>
));
return (
<div>
<button onClick={this.handleClickStart}>Start</button>
<button onClick={this.handleClickStop}>Stop</button>
<hr />
<div className="MotionText">{innerTree}..</div>
</div>
)
}
How this helps is that, the key becomes different than previously assigned key to first span being rendered. Any way by which you can make the key different than previous will help you have this animation. Otherwise React will not render it again and hence you will never see this in animation.

How to combine JSX component with dangerouslySetInnerHTML

I'm displaying text that was stored in the database. The data is coming from firebase as a string (with newline breaks included). To make it display as HTML, I originally did the following:
<p className="term-definition"
dangerouslySetInnerHTML={{__html: (definition.definition) ? definition.definition.replace(/(?:\r\n|\r|\n)/g, '<br />') : ''}}></p>
This worked great. However there's one additional feature. Users can type [word] and that word will become linked. In order to accomplish this, I created the following function:
parseDefinitionText(text){
text = text.replace(/(?:\r\n|\r|\n)/g, '<br />');
text = text.replace(/\[([A-Za-z0-9'\-\s]+)\]/, function(match, word){
// Convert it to a permalink
return (<Link to={'/terms/' + this.permalink(word) + '/1'}>{word}</Link>);
}.bind(this));
return text;
},
I left out the this.permalink method as it's not relevant. As you can see, I'm attempting to return a <Link> component that was imported from react-router.However since it's raw HTML, dangerouslySetInnerHTML no longer works properly.
So I'm kind of stuck at this point. What can I do to both format the inner text and also create a link?
You could split the text into an array of Links + strings like so:
import {Link} from 'react-router';
const paragraphWithLinks = ({markdown}) => {
const linkRegex = /\[([\w\s-']+)\]/g;
const children = _.chain(
markdown.split(linkRegex) // get the text between links
).zip(
markdown.match(linkRegex).map( // get the links
word => <Link to={`/terms/${permalink(word)}/1`}>{word}</Link> // and convert them
)
).flatten().thru( // merge them
v => v.slice(0, -1) // remove the last element (undefined b/c arrays are different sizes)
).value();
return <p className='term-definition'>{children}</p>;
};
The best thing about this approach is removing the need to use dangerouslySetInnerHTML. Using it is generally an extremely bad idea as you're potentially creating an XSS vulnerability. That may enable hackers to, for example, steal login credentials from your users.
In most cases you do not need to use dangerouslySetHTML. The obvious exception is for integration w/ a 3rd party library, which should still be considered carefully.
I ran into a similar situation, however the accepted solution wasn't a viable option for me.
I got this working with react-dom in a fairly crude way. I set the component up to listen for click events and if the click had the class of react-router-link. When this happened, if the item has a data-url property set it uses browserHistory.push. I'm currently using an isomorphic app, and these click events don't make sense for the server generation, so I only set these events conditionally.
Here's the code I used:
import React from 'react';
import _ from 'lodash';
import { browserHistory } from 'react-router'
export default class PostBody extends React.Component {
componentDidMount() {
if(! global.__SERVER__) {
this.listener = this.handleClick.bind(this);
window.addEventListener('click', this.listener);
}
}
componentDidUnmount() {
if(! global.__SERVER__) {
window.removeEventListener("scroll", this.listener);
}
}
handleClick(e) {
if(_.includes(e.target.classList, "react-router-link")) {
window.removeEventListener("click", this.listener);
browserHistory.push(e.target.getAttribute("data-url"));
}
}
render() {
function createMarkup(html) { return {__html: html}; };
return (
<div className="col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3 col-lg-8 col-lg-offset-2 post-body">
<div dangerouslySetInnerHTML={createMarkup(this.props.postBody)} />
</div>
);
}
}
Hope this helps out!

How to make React and Meteor fit together

I don't know if it's more a React or Meteor concern, maybe both, but I am currently building a web app with these two frameworks and I am facing a programmer issue. I am not a Javascript developer but a Java developer (I use daily GWT), so maybe I made some rookie mistakes.
My app keeps growing and I have more and more React components, about twenty or so. Now that I have a view that is fine, I have added some functionalities to my components but it turns up I add more and more logic in the react components which is, I believe, against MVC principles.
However, I don't know how to move the logic in "Meteor controller components". Right now, I use Meteor for its model and that's just about all. I saw many times this Pete Hunt's talk and how he built his application but it has only one 'simple' component.
In fact, without React, the view would be in html files, defined with templates. The controller would be in js files and the logic will appear to be there. I can clearly see the split between the view and the controller.
Html file (from leaderboard example):
<template name="leaderboard">
...
</template>
<template name="player">
<div class="player {{selected}}">
...
</div>
</template>
Javascript file (from leaderboard example):
...
Template.leaderboard.players = function () {
return Players.find({}, {sort: {score: -1, name: 1}});
};
Template.leaderboard.selected_name = function () {
var player = Players.findOne(Session.get("selected_player"));
return player && player.name;
};
...
Since React is javascript, it's really easy and tempting to put all we want in React components.
I am aware of these frameworks are relatively new for everybody but I wonder wheter some conventions exist about how to design such an MVC application in order to have a flexible and maintainable web application, any guidelines to follow? I am not looking for the 'best' way to do it but for some opinions.
Note: I deliberately didn't put a lot of code here to not be focus on it but feel free to illustrate your answer with whatever you want (code, schema, links...).
Here is an example of what I am doing. In this example, everything is done in react classes, maybe it's a the best way to do it, maybe not, I need your thoughts.
To sum up, it creates a list of elements (Boostrap list group) from an array given as input (something like [{name: itemName1, type:itemType1}, {name: itemName2, type:itemType2} ...] which generates a view like:
itemName1
itemName2
...
Each item as its own style according to its type. Then through the input text box, user can make a search trough this list, it filters the list and generates a new one that composed with the matching elements (the search algorithm is not right and will be changed). Plus, there are additional commands with certain keyboard key. Everything works fine but as you can notice, all is in react classes, I don't figure out how to fit Meteor with React.
Meteor file:
if (Meteor.isClient) {
Meteor.startup(function() {
//Build the view
React.renderComponent(
<Search items={initialItems}/>,
document.getElementById('main')
);
});
}
React file:
Search = React.createClass({
getInitialState : function() {
return (
{
items : flat(this.props.items),
active : 0
}
);
},
setListVisibility: function(visibility) {
this.refs.list.getDOMNode().style.visibility = visibility;
},
onchangeHandler: function() {
var re = new RegExp(this.refs.search.getDOMNode().value, "i");
var res = [];
//filter on props.items and not state.items
flat(this.props.items).map(function(item){
if(item.name.search(re) >= 0)
res.push(item);
});
this.setState({ items : res, active : 0});
},
onkeydownHandler: function(event){
if(event.key == "ArrowDown" || event.key == "ArrowUp"){
var shift = event.key == "ArrowDown" ? 1 : -1;
var newActive = this.state.active + shift;
if(newActive >= 0 && newActive < this.state.items.length)
this.setState({ active : this.state.active + shift });
} else if(event.key == "ArrowRight"){
if(this.state.items.length > 0){
var item = this.state.items[this.state.active];
var newItems = retrieveItem(this.props.items, item.name, typeToSubType[item.type]);
newItems = flat(newItems);
if(newItems.length > 0)
this.setState({ items : newItems, active : 0 });
}
} else if(event.key == "ArrowLeft"){
this.setState({ items : flat(this.props.items), active : 0});
} else if(event.key == "Enter"){
if(this.state.items.length > 0){
var item = this.state.items[this.state.active];
console.log("Add "+item.name+" "+item.type+" to the view");
}
}
},
render: function () {
return (
<div>
<nav className="navbar navbar-default" role="navigation">
<div className="container-fluid">
<div className="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form className="navbar-form navbar-left" role="search">
<div className="form-group">
<input ref="search" type="text" className="form-control" placeholder="Search" size="100"
onChange={this.onchangeHandler}
onKeyDown={this.onkeydownHandler}
onFocus={this.setListVisibility.bind(this, "visible")}
onBlur={this.setListVisibility.bind(this, "hidden")}/>
</div>
</form>
</div>
</div>
</nav>
<List ref="list" items={this.state.items} active={this.state.active}/>
</div>
);
}
});
List = React.createClass({
render: function () {
var createItem = function(item, index) {
var cl = "list-group-item";
if(index == this.props.active)
cl += " active";
var gly = "glyphicon ";
switch(item.type){
case "dimension":
gly += "glyphicon-certificate";
break;
case "hierarchy":
gly += "glyphicon-magnet";
break;
case "level":
gly += "glyphicon-leaf";
break;
case "measure":
gly += "glyphicon-screenshot";
break;
}
return (<a href="#" className={cl} key={item.type+"/"+item.name}>
<span className={gly}></span>{" "}{item.name}
</a>);
};
return (
<div className="list-group search-list">
{this.props.items.map(createItem, this)}
</div>
);
}
});
Your approach is sound: Meteor for the model and React for the View and ViewController.
Anything functionality that has nothing to do with presentation should be in the model (business logic, validation rules, etc).
Anything to do with presentation and responding to user input should be in React (input, validation output, etc).
Today you could consider this nice peace of code:
https://github.com/reactjs/react-meteor
This repository defines a Meteor package that automatically integrates the React rendering framework on both the client and the server, to complement or replace the default Handlebars templating system.
As of Meteor 1.3 there is an officially supported way to integrate React with Meteor. So for anyone stumbling across this question today, here's the Meteor 1.3+ answer:
To use React as Meteor's view layer, first add the React packages from npm:
meteor npm install --save react react-dom
Now you can simply import React and use it in your project. To render a simple React component, create a simple HTML container:
client/main.html
<body>
<div id="app"></div>
</body>
And render your React component in it:
client/main.jsx
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
class HelloWorld extends React.Component {
render() {
return <p>Hello World!</p>;
}
}
Meteor.startup(() => {
render(<HelloWorld />, document.getElementById('app'));
});
To use reactive Meteor data sources such as Minimongo collections within React components, you should use the react-meteor-data package.
Read more in the official Meteor guide

Categories