Can We Style Inside A Const In React - javascript

I am new to react , can i style inside a const
Here is my code
const initialStudentCounter =
'Students' + ' ' + JSON.stringify(studentCountInitial);
I need to style this "JSON.stringify(studentCountInitial)"
I tried this way , but didn't work
const initialStudentCounter =
'Students' + ' ' + <span style={color : 'red'}>JSON.stringify(studentCountInitial)</span> ;
Can some one help me please

You don't need JSON.stringify in JSX. You do need to insert this into your JSX with a surrounding element. You shouldn't need the + for concatenating strings anymore either.
export default function App() {
const studentCountInitial = 4;
const initialStudentCounter = <div>Students <span style={{color : 'red'}}>{studentCountInitial}</span></div>;
return (
initialStudentCounter
);
}

In React, you need to use double curly brackets (The first set of brackets is telling the compiler that this is Javascript, the second set is telling the compiler that this is an object.) when styling elements. Also, surround your element with a string.
Code:
const initialStudentCounter =
'Students' + ' ' + `<span style={{ color : 'red' }}>${JSON.stringify(studentCountInitial)}</span>`;

There are at least two problems here:
You're concatenating a string with a JSX element.
Your style attribute's value is missing a pair of curly braces for opening and closing an object (the first pair merely lets you use JS syntax).
const initialStudentCounter = <p>Students <span style={{color : 'red'}}>{JSON.stringify(studentCountInitial)}</span></p>;
I also suspect that studentCountInitial is just a plain number and thus it probably doesn't need to be stringified. So you can probably just do this...
const initialStudentCounter = <p>Students <span style={{color : 'red'}}>{studentCountInitial}</span></p>;
If you really need to then convert that JSX element to a string, you could use something like ReactDOMServer.renderToStaticMarkup(), but that's likely unnecessary.

Related

Adding a line break or line-wrap in JavaScript not working as anticipated

I am using this line:
 
userResultMapOne = "But your value of " + userInputMapOne + " \nis too high for this scenario."
I have tried multiple different ways of using \n to get a line break. Actually, what I really want is for the text to wrap to the next line on mobile devices, but for some weird reason, the text just goes off screen (it is being displayed in a Bootstrap modal).
What is the correct way to allow JS innerHTML DOM modifications to wrap on small devices especially in a Bootstrap modal?
*Edit - I have done more investigation, but I am still none the wiser on why one of the two outputs is correct.
Here's the two inspect outputs. The first one shows the line not wrapping, but the second one, correctly, shows the line wrapping. Can anyone see why that is?
instead of \n replace <br>
Your are probably using innerHTML to insert your string, you should use innerText
const userInputMapOn = '[USER_VALUE]';
const userResultMapOne = "But your value of "+ userInputMapOn + "\nis too high for this scenario";
const p1 = document.querySelector('#innerHTML');
const p2 = document.querySelector('#innerText');
p1.innerHTML = '_ With innerHTML : ' + userResultMapOne;
p2.innerText = '_ With innerText : ' + userResultMapOne;
<p id="innerHTML"></p>
<p id="innerText"></p>
With Template literals :
const userInputMapOn = '[USER_VALUE]';
const userResultMapOne = `But your value of ${userInputMapOn} \nis too high for this scenario`;
const p = document.querySelector('p');
p.innerText = userResultMapOne;
<p></p>
Edit :
If you need to insert HTML along with the string, just replace the \n with <br> and use innerHTML like so :
const userInputMapOn = '[USER_VALUE]';
const userResultMapOne = `But your value of <b>${userInputMapOn}</b> \nis too high for this scenario`;
const p = document.querySelector('p');
p.innerHTML = userResultMapOne.replace(/(?:\r\n|\r|\n)/g, '<br>');
<p></p>

Find a string in structured HTML and replace it while maintaining the structure

Let's say I have the following text:
...at anyone who did not dress...
, where I need to find and replace "did not" with "did't" The task is simple until the text has styles and it becomes:
...at anyone who <span style='color: #ff0000;'>did</span>not dress...
If I just do
obj.innerText.replace("did not", "did't"),
then the style will not be saved, and
obj.innerHtml.replace("did not", "did't")
will not find
Is there an elegant solution?
UDP: there is a position in the text of the beginning and end of a phrase/word, as well as an index in case of repetition
const html = document.getElementsByTagName('p')[0].innerHTML;
const tags = html.match(/<\/?[^>]+(>|$)/g) || [];
const textTrue = html
.replace(/<\/?[^>]+(>|$)/g, '')
.replace('did not', "didn't");
var lastIndex = 0;
const tagsIndexs = tags.map((item) => {
lastIndex = html.indexOf(item, lastIndex);
return lastIndex;
});
const output = tags ? tags.reduce((result, tag, index) => {
return (
result.substr(0, tagsIndexs[index]) +
tag+
result.substr(tagsIndexs[index])
);
}, textTrue): textTrue;
document.getElementById('result').innerHTML = output;
<p>d<span style="color: #FF0000">id </span>not</p>
<div id='result'></div>
if 'not' is not styled(as shown in the example) the best approach I can think of is find all 'did' occurrences and then check if there is 'not' in the neighborhood. If yes remove the 'not' and replace the did with didn't. It is however performance intensive since you can not go for replace, but use indexOf in a while loop and manipulate the html string manually. Additionally if the styling varies(<span>,<b>,<i>..) it will be very difficult(if not impossible) to come with a valid criteria to evaluate the existence of 'not' in the neighborhood of the 'did'. The same approach can be used on 'not' instead of did, but again it really depends on the styling you need to preserve.

Jest Equality Matcher For Strings That Disregards Whitespace

Jest's toEqual matcher takes whitespace into account when checking for equality. When formatting the expected value in tests it is impossible to do so in a way that matches a string containing newlines, tabs etc.
Does Jest offer a way to disregard whitespace when matching?
Note: I edited the question to make it more generic.
As #Timo says, the only way of doing this appears to be with a custom matcher. Here is one that compresses all whitespace down to a single space for readability based on Jest's toEqual matcher. It will deal with tabs, newlines etc. It will give you pretty output like the included Jest matchers:
//matchStringIgnoringWhiteSpace.js
import { replace, map, equals } from 'ramda';
import { matcherHint, printReceived, printExpected } from 'jest-matcher-utils';
import diff from 'jest-diff';
const replaceWhitespace = replace(/\s+/g, ` `);
const compressWhitespace = map(replaceWhitespace);
const name = `toEqualWithCompressedWhitespace`;
export default function (received, expected) {
const [
receivedWithCompresssedWhitespace,
expectedWithCompresssedWhitespace,
] = compressWhitespace([received, expected]);
const pass = equals(
receivedWithCompresssedWhitespace,
expectedWithCompresssedWhitespace
);
const message = pass
? () =>
`${matcherHint(`.not.${name}`)}\n\n` +
`Uncompressed expected value:\n` +
` ${printExpected(expected)}\n` +
`Expected value with compressed whitespace to not equal:\n` +
` ${printExpected(expectedWithCompresssedWhitespace)}\n` +
`Uncompressed received value:\n` +
` ${printReceived(received)}\n` +
`Received value with compressed whitespace:\n` +
` ${printReceived(receivedWithCompresssedWhitespace)}`
: () => {
const diffString = diff(
expectedWithCompresssedWhitespace,
receivedWithCompresssedWhitespace,
{
expand: this.expand,
}
);
return (
`${matcherHint(`.${name}`)}\n\n` +
`Uncompressed expected value:\n` +
` ${printExpected(expected)}\n` +
`Expected value with compressed whitespace to equal:\n` +
` ${printExpected(expectedWithCompresssedWhitespace)}\n` +
`Uncompressed received value:\n` +
` ${printReceived(received)}\n` +
`Received value with compressed whitespace:\n` +
` ${printReceived(receivedWithCompresssedWhitespace)}${
diffString ? `\n\nDifference:\n\n${diffString}` : ``
}`
);
};
return {
actual: received,
expected,
message,
name,
pass,
};
};
To register the custom matcher you need to add it to your setupTests files. First register setupTests in your jest.config.js using the setupFilesAfterEnv field:
setupFilesAfterEnv: `<rootDir>/path/to/setupTests.js`,
And then register the custom matcher on the expect object.
//setupTests.js
import toMatchStringIgnoringWhitespace from "<rootDir>/path/to/matchStringIgnoringWhiteSpace";
expect.extend({
toMatchStringIgnoringWhitespace: toMatchStringIgnoringWhitespace
});
If you are using TypeScript you will also want to add the typings to the expect object following the instructions here.
As far as I know, there is no way to achieve this with Jest out of the box.
However, it is pretty straightforward to write your own reusable matcher using expect.extend. Remove all whitespace from both strings, e.g. via str.replace(/\s/g, ''), and compare the strings.
While this is not a direct answer, you can also do:
mockedFunction.mock.calls[0] // To get array of arguments
// or
mockedFunction.mock.calls[0][0] // to get first argument and so on
And then compare with equality.

Manipulate a string and return it as html

I have a string coming in from a CMS like this:
MSRP Base Price †
The string is not mutable and I need to replace the † wrapped around superscript tags like this:
<sup>†</sup>
However, with the str.replace method, I'm using:
var superLabel = str.replace(new RegExp('†'), '<sup>†</sup>');
superLabel is returning this: MSRP Base Price < sup>†< sup>
You mentioned React in your question. React will automatically decode your string to avoid XSS attacks.
You need to use dangerouslySetInnerHTML to set your value.
Example:
// Does not work
const string = '<sup>†</sup>';
return <div>{string}</div>;
// Works
const string = '<sup>†</sup>';
return <div dangerouslySetInnerHTML={string} />;
Be careful though and make sure your input is safe.
The following is one way to do what you need except for what's mentioned in the answer accounting for React, which I'm not familiar with.
var fromCMSPrefix = 'MSRP Base Price'
var fromCMS = 'MSRP Base Price †';
var superLabel = '<sup>' + fromCMS.substr(fromCMSPrefix.length).trim() + '</sup>';
Here's another:
var fromCMS = 'MSRP Base Price †';
var superLabel = '<sup>' + fromCMS.replace('MSRP Base Price', '').trim() + '</sup>';

variable array + regular expression not working together?

im making a small smiley script , what it does is to change ::1:: into an image html for a div.
the code as follow:
var smileys = {
'1': 'http://domain.com/smiley1.gif',
'2': 'http://domain.com/smiley2.gif',
'3': 'http://domain.com/smiley3.gif'
};
function checksmileys(){
x$('.message').each(function()
var start = '<img src="';
var end = '">';
x$(this).html( x$(this).html().replace(/::(\d+)::/g, start + smileys['$1'] + end) );
});
Checksmileys function is triggered by user event.
However it is not able to get the digit(which is the id) out of a sentence.
It kept on producing this <img src="undefined">
My HTML example as follows:
<div id="chat">
<ul>
<li class="message">Hi john</li>
<li class="message">what are you doing</li>
<li class="message">::1:: nothing</li>
<li class="message">hi</li>
<li class="message">nice to meet you ::1::</li>
</ul>
</div>
Where is my problem here?
I guess you need a function here:
html = html.replace(/::(\d+)::/g, function($0, $1) { return start + smileys[$1] + end })
here's when the functional form of html() comes in handy
$(this).html(function(_, oldhtml) {
return oldhtml.replace(/::(\d+)::/g, function($0, $1) {
return start + smileys[$1] + end;
})
})
In JavaScript, property names don't have prefixes like they often do in PHP. The name of the property you create in your smileys object is 1, not $1, so change smileys['$1'] to smileys['1'].
Update: From your comment below, it seems you're trying to use $1 to refer to the capture group. That only works when $1 is part of the string you pass in, but the expression start + smileys['$1'] + end is evaluated before the call to replace and then passed into it. smileys['$1'] will be undefined.
Since you're trying to do a lookup, your best bet is to pass in a function that does the lookup:
x$(this).html( x$(this).html().replace(/::(\d+)::/g, function(m, c1) {
return start + smileys[c1] + end;
}) );
c1 is the text of the first capture group. More
You've called it an array, which I'm guessing is because you're used to the term "associative array" from PHP. Your smileys object is just an object, not an array. In JavaScript, when we say "array", we mean something created via [] or new Array, which has specific handling for a certain class of property names (numeric ones), a special length property, and some handy array-like functions. What you've done with smileys is perfectly fine and completely normal, we just tend not to use the word "array" for it ("map" is more common in the JS world).

Categories

Resources