Passing a number to a component - javascript

I am trying to pass a number to a React component but it is getting parsed as string (jsfiddle). How do I make React understand that I am passing a number? Should I cast the string to a number in the component?
var Rectangle = React.createClass({
render: function() {
return <div>
<div>{this.props.intValue + 10}</div>
<div>{this.props.stringValue + 10}</div>
</div>;
}
});
React.render(<Rectangle intValue="10" stringValue="Hello" />
, document.getElementById('container'));
<script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>

It seems that in case of integers (and actually for strings as well) I should be passing the numbers via {} like so:
React.render(<Rectangle intValue={10} stringValue={"Hello"} />, document.getElementById('container'));

You can either use:
<MyComponent param1={10} param2={20} />
Or:
<MyComponent {...{param1: 10, param2: 20}} />

Related

How to get React to parse new lines from components? [duplicate]

I have the following React code:
render() {
const str = 'Line 1. **new-line** Line 2.';
return (
<p> {str} </p>
);
}
I would like the output to be:
Line 1.
Line 2.
That is - to add a new line between the words.
I have tried \n but it does not work.
How could this be accomplished?
Edit: The string is received from a server.
Set CSS-Style for the paragraph as below, it will break line on \n and wrap text according to parent width.
white-space: pre-wrap;
or
white-space: pre-line;
A more traditional approach is to just create an array with your strings, with a <br /> tag in between. Arrays are, as of React v16 a valid return value for Elements.
class App extends React.Component {
render() {
const arr = ['Line 1. ', <br />, 'Line 2.'];
return (
<p> {arr} </p>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
If you are getting a string from some API, you could create such an array by finding all <br /> substrings and replace them with actual JSX <br />'s. The following code will take your string and do a string split on every instance of <br />. This will give you ['Line 1. ', '', 'Line 2.']. As you can see, every odd element in the array is where we want to push a JSX <br />. We can do that quite simply in a loop.
class App extends React.Component {
render() {
const str = 'Line 1. <br /> Line 2.';
const arr = str.split(/<br \/>/);
const resultArr = [];
arr.forEach((item, i) => {
if(i%2===0) resultArr.push(<br />);
resultArr.push(item);
});
return (
<p> {resultArr} </p>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
The other approach is to either use dangeourslySetInnerHTML() or use template literals.
You could use template literals for that along with the css rule white-space: pre to preserve newlines. See my demo below:
class App extends React.Component {
render() {
const str = `Line 1.
Line 2.`;
return (
<p style={{whiteSpace: 'pre'}}> {str} </p>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
style={{ whiteSpace: 'break-spaces' }}
For that purpose you have to use something called dangerouslySetInnerHTML.
Example
render() {
const str = 'Line 1. <br /> Line 2.';
return (
<p dangerouslySetInnerHTML={{ __html: str }}/>
);
}
You could accomplish this by using CSS instead.
p {
white-space: pre;
}
You render then becomes:
const str = "Line 1.\nLine 2."
return (<p>{str}</p>)
This is what I do.
<span>{<br/>}</span>
Using CSS - (Simply add it to content's div. Wraps and adds new-line for every '\n' appended to content)
p {
white-space: pre-wrap;
}
Use React's dangerouslySetInnerHTML - (Apply to parents div and parse any tags in the value field. Works similar to innerHTML.)
<div dangerouslySetInnerHTML={{__html: '<p>First · Second</p>'}}></div>
Link for more information about dangerouslySetInnerHTML:
[https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml][1]
You can easily achieve it by doing the following:
myTextHere={<span>Hello<br />Hi</span>}
Output will be like this:
Hello
Hi

Add <br> tag using replaceAll() in javascript

I have this string:
export default function App() {
const string = 'test data,cars,colors,demo';
return (
<div className="App">
<h1>Hello {string.replaceAll(',','<br>')}</h1>
</div>
);
}
I expect:
test data<br>cars<br>colors<br>demo
But i get one string without breack inside my string. How to achieve what i expect using replaceAll()?
In order to display html from string you have to use dangerouslySetInnerHTML
export default function App() {
const string = 'test data,cars,colors,demo';
return (
<div className="App">
<h1 dangerouslySetInnerHTML={{ __html: `Hello ${string.replaceAll(',','<br>')}`}}></h1>
</div>
);
}
Assuming this is a React application you need to use dangerouslySetInnerHTML to add the new HTML to the page.
function Example() {
const string = 'test data,cars,colors,demo';
const html = `Hello ${string.replaceAll(',', '<br>')}</h1>`;
return (
<div className="App">
<h1 dangerouslySetInnerHTML={{ __html: html }} />
</div>
);
}
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
I don't suggest you dangerouslySetInnerHTML. It introduces both security and performance issues, and even if you are working on learning project, you better avoid such an approach.
The reason why your code does not work, JSX does not magically convert string "<br>" into appropriate element (until there is dangerouslySetInnerHTML, sure).
But JSX can render arrays just fine. It allows us to split initial string into elements: string.split(', ') and then inject JSX's <br /> with the help of .flatMap()(think about it as if .join() could return array with additional elements in between elements of source array).
{
string.
split(', ').
flatMap((el, index) => index ? [<br />, el]: el)
}
This approach is way more powerful than dangerouslySetInnerHTML since instead of simple BR you may use any JSX tree with React custom components, context and event handlers.
Another approach is to replace ', ' with newlines and apply CSS style white-space: pre-wrap(check white-space docs on all values available)

Set a multiline string as defaultValue in react-ace Ace Editor

When using the react-ace (Ace Editor) library, I find myself in the need to define the defaultValue property as a code block in the JSX format (the editor mode I have left in JavaScript), like this:
<div style={{height: "100%", width:"100%"}}>
<AceEditor
mode="javascript"
theme="github"
onChange={this.onChange}
name="UNIQUE_ID_OF_DIV"
defaultValue="export default function MyComponent({ children }) {..."
width="100%"
height="100%"
editorProps={{
$blockScrolling: true
}}
/>
</div>
When declaring defaultValue to get something like this:
export default function MyComponent({ children }) {
return (
<>
<header>
<a>
<Image
priority
className={utilStyles.borderCircle}
height={108}
width={108}
alt={name}
/>
</a>
<h2 className={utilStyles.headingLg}>
<a className={utilStyles.colorInherit}>{name}</a>
</h2>
</header>
<main>{children}</main>
{!home && (
<div className={styles.backToHome}>
<a>← Home</a>
</div>
)}
</>
)
}
The editor returns...
How can I get a multiline string into the editor as a default value?
You can use template literals to do the multiline statements.
In the official docs of AceEditor mentioned that you can pass a string for value attribute which should be reflected in the editor so when you pass a string inside " " it should not take new line so, when you use template literals ie,${``} we can give multiline sentences
so, its similar to how we pass a value in react to attributes
attribute-name = {"here we specify what should be the value"}
as in our case it should be a string which can be in multiple line
so attribute-name = {${``}}
Example:
value={`${`
//firstline
//secondline
...
//n line`}`}
reference :
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

Dynamically made strings for id in JSX

I want to make id like this dynamically.
<div id="track_1"></div>
<div id="track_2"></div>
So I gave the id like this from parent component.
export default function Components(props) {
return (
<AudioTrack trackNum="1"/>
<AudioTrack trackNum="2"/>
)
}
then in my AudioTrack Component I got the trackNum and want to use like this
const AudioTrack = (props) => {
return(
<div id="track_{props.trackNum}" ></div>
);
}
Howeber it doesn't work.
Is there any good way?
Since the div prop isn't a constant string, you need {} to indicate an expression, and then either use + to concatenate or a template literal with ${}:
<div id={`track_${props.trackNum}`}></div>

Render a component within another in React

When a state is changed, React triggers componentDidUpdate() method, and by then I do:
componentDidUpdate: function () {
React.render(new SubmitButton, $('.uploader-submit').get(0));
}
As you saw, I'm rendering a SubmitButton when a specific state is changed, but my question is: is this the best behavior to get this feature done?
My scenario is: I'm uploading a photo. When the input[type=file] is changed, I create a new state property and then the componentDidUpdate() is triggered, invoking the SubmitButton.
This is my render() method:
render: function () {
return (
<div className="uploader">
<header className="uploader-header">
<div className="uploader-actions pull-left">
<div className="uploader-submit"></div>
<CancelButton router={this.props.router} />
</div>
<UploadButton callback={this.imageSelectedCallback} />
</header>
<Preview imageUri={this.state.imageUri} />
</div>
)
}
Couldn't I do something like the <Preview /> component? I mean, it is there, but something just appears when this.state.imageUri is different of null. This is the implementation of Preview:
var Preview = {
render: function () {
return (
<img src={this.props.imageUri} />
)
}
};
module.exports = React.createClass(Preview);
Yes, I know — "Preview" is invisible by default because it is an image, but I want to know if there's another approach to reach what I want: to show something based on a state, using the render method.
React doesn't render falsy values, be it a component or an attribute (like in the Preview case), e.g.
<div>{null}</div>
<img src={null} />
renders to
<div></div>
<img/>
So typically you just create a variable and conditionally assign it a component or null as was also suggested in another answer:
var button = null;
if(myConditionForShowingButton) {
button = <SubmitButton />;
}
-- or simply --
var button = myConditionForShowingButton ?
<SubmitButton /> :
null;
In cases where the component gets bigger it's typically more readable and cleaner to have a subroutine for rendering that part
var complexComponent = condition ?
this.renderComplexComponent() :
null
Yes. If-Else in JSX.
render: function () {
var submitButton;
if (this.state.imageSelected)
submitButton = <SubmitButton />;
return (
<div className="uploader">
<header className="uploader-header">
<div className="uploader-actions pull-left">
<div className="uploader-submit">{ submitButton }</div>
<CancelButton router={this.props.router} />
</div>
<UploadButton callback={this.imageSelectedCallback} />
</header>
<Preview imageUri={this.state.imageUri} />
</div>
)
}

Categories