Changing a html variable in react - javascript

I have the following variable in React
let Example = (
<div>
Hello World
</div>
);
I would like to change its content (text, tags, etc.)
Is that possiable to do?
What is the type of this variable?
Thanks

You can just overwrite your variable in another statement and this is a jsx Element.
https://reactjs.org/docs/introducing-jsx.html

Maybe you are looking for react components and props?
https://reactjs.org/docs/components-and-props
The type of your variable would be a JavaScript function and you can use react props to modify your content.

Use functions!
const myContent = () => {
// Some js
return 'Hello!';
}
const Example = () => (
<div>
{myContent()}
</div>
);

If you want to change the content of a JSX snippet that's a crystal clear hint that what you need is a component.
In your example, you can try something like this.
const SayHello = ({ name }) => <div>Hello {name}</div>
Then you can use it as a regular component.
<SayHello name="world" />
You can bound the value to a variable, and then the component will be updated with any update of that variable.
let name = this.aMethodToGetAValue();
return <SayHello name={name} />

Related

Is there a way to find out if a JS function return JSX or not?

I have a dynamic list. Developers can either provide a URL or a component for that list. Both of them are basically functions:
<List
{...otherProps}
create={params => `create_a_dynamic_url`}
/>
<List
{...otherProps}
create={Form}
/>
and in my List.jsx I have a create prop that is a function.
I should either directly render it using {create} or call it first and then navigate the user to that URL.
For both of them, the typeof operator returns function. Is there a way to find out if their return value is JSX or not?
It is not reliably possible to check if the function is a React component,
but it might help you to check for the React element (which is easy).
Check the React element
You can call the function yourself, assign the return value to a variable, and check if that is a React element.
function App(){
return <>
<List id={'A'} create={ props => <>(My React component)</> } />
<List id={'B'} create={ params => `create_a_dynamic_url` } />
</>;
}
export const List = props => {
const { create, id } = props;
// -- Check for the React components `.name`:
console.log('(List.js) create.name:', id, create?.name);
// --
// Create either a ReactElement from the ReactComponent,
// or the string from the string constructor function:
// --
const myElementOrString = create();
// -- Check for string or ReactElement:
const isString = typeof myElementOrString === 'string';
const isReactElement = !isString;
// --
return <>
<p>{ id }</p>
<div>
<b>The React element is:</b>
{ isReactElement ? myElementOrString : '(none)' }
</div>
<p>
<b>The string is:</b>
{ isString ? '"' + myElementOrString + '"': '(none)' }
</p>
</>;
};
Alternatively you could also check for myElementOrString.hasOwnProperty('$$typeof') or other React specific properties,
but I would be careful with that, because these (or some of them) are "implementation details" you should not rely on.
The .name property
Also note that the function received by your List component via the create property
will have a .name property, which will be different depending on some circumstances, e.g.:
an anonymous function will have the name "create" (the property name)
a named component will have the name of the component
a named function will have the name of the function
... ?
You might be able to check the .name property, but I think that approach would not
be reliable (e.g. this depends on that the developer knows about this, e.g. has to name the function in a specific way.)

How to create dynamic states and update it in react?

I have list of data getting fetched from the API and each index in data is creating a <div> which consist of some information and button along with it.
Now when I click on button, a textarea and submit button should open for that <div> and closes when clicked again.
I tried to create this here.
To achieve this, I am creating n number of states and update the state when user click the button.
How can I achieve this and where am I going wrong ?
This is a working example of what you're looking for:
const { useState } = React;
const Counter = () => {
const [count, setCount] = useState(0);
const data = [
{"id":100},
{"id":200},
{"id":300},
{"id":400},
];
const [show,setShow] = useState([]);
const handleClick = id => e => {
const showCopy = [...show];
if(show[id]){
showCopy[id] = false;
} else {
showCopy[id] = true;
}
setShow(showCopy);
}
return (
<div>
{
data.map((k,v) => (
<div key={v}>
<div>
<p>Data{v+1}</p>
<p>Some More Information</p>
</div>
<button onClick={handleClick(v)}>Update</button>
<br/>
{
show[v] ? <div>
<textarea></textarea>
<button id={v}>Delete</button>
</div> : <></>
}
<hr/>
</div>
))
}
</div>
)
}
ReactDOM.render(<Counter />, document.getElementById('app'))
A couple things were wrong in your sample code:
Improper use of dot operators instead of brace operators
The JS dot (.) operator is used to access named attributes associated with the given JS object. In these particular cases, the values v and id are dynamic, and not the true names of the attributes desired. Using the brace [] operators allows you to access the dynamic value stored in the variable.
Improper array state update
In your example, the code you had written was creating a new array based on the contents of the previous array and adding a new object every time with a literal attribute named id. In the updated code, a copy of the original state array is created and the desired boolean value with index id is modified.

Output each child with a wrapper from React.Children array

I have this reusable component.
export const ListItems = ({ controls, children }) => {
const content = controls ? <PrivateComponent>{ children }</PrivateComponent> : children;
return <ul>{ content }</ul>
}
Seems pretty-straight forward. The idea is that, in PrivateComponent, I wanna wrap each of the children with an extra wrapper, something like this:
export const PrivateComponent = ({ children }) => {
const _children = React.Children.toArray(children);
return (
<div>{ _children.map(child => <SomeWrapper>{ child }</SomeWrapper> ) }</div>
);
}
My question is, is it correct to render child this way, or should I use cloneElement? Also, what should I use for the key of SomeWrapper in the map function?
is it correct to render child this way, or should I use cloneElement?
You can use the child instance directly, there is no problem there. You need cloneElement only if you want to change / add any props or swap out its own children, or if you need a duplicate because you intend to insert "the same child" in two different location in your DOM.
what should I use for the key of SomeWrapper in the map function?
You can use React.Children.map(children, function[(thisArg)]) (doc) which will automatically add keys.

React add a variable name attribute

What is the cleanest way in React to add a variable name attribute?
The end result I want is: <div data-flag>Hello</div> where the name data-flag is stored in a const variable.
The ways I found now are:
const DATA_FLAG = 'data-flag';
const Hello = ({ name }) => {
const dataAttrs = { [DATA_FLAG]: true }
return <div {...dataAttrs}>Hello {name}</div>;
}
Or this one-line version (but I find it less readable):
const Hello = ({ name }) => <div {...{ [DATA_FLAG]: true }}>Hello {name}</div>;
You can play with it in this JSFiddle
These versions work fine if the attribute was variable (true or false) but in my case it's always true so I find it a bit over-killed and the syntax complex.
I would love to know if there is a cleaner way to achieve it.
I know that the best approach is to apply it directly like: <div data-flag>Hello</div> but I really need to store data-flag in a constant (as shared by other components).
You could create a React element without using the JSX syntax. Something like this should work:
const DATA_FLAG = 'data-flag'
const Hello = ({ name }) => {
const dataAttrs = { [DATA_FLAG]: true }
return React.createElement('div', dataAttrs, `Hello ${name}`)
}
This only really makes the way you're passing in the attributes look easier on the eyes though. Don't think you'll get around defining a dataAttrs object for your props.

How do I join two elements and then render them in React?

It's simple. I have a render function with two elements
render() {
let elem1 = <div>Foo</div>;
let elem2 = <div>Bar</div>;
return(elem1 + elem2); // How do I render elem1 below elem2?
}
I want the output to be equivalent to this
<div>
Foo
</div>
<div>
Bar
</div>
Simple like this:
render() {
let elem1 = <div>Foo</div>;
let elem2 = <div>Bar</div>;
return (
<div>
{elem1}
{elem2}
</div>
);
}
You should read and practice more JSX in here
If you are using React > 16.2 you can use the new Fragment component
render() {
let elem1 = <div>Foo</div>;
let elem2 = <div>Bar</div>;
return (
<React.Fragment>
{elem1}
{elem2}
<React.Fragment/>
);
}
The main advantage over using a div is that it doesn't add any elements to the page and is more readable than returning an array.
render() {
let elements=new Array();
elements.push(<div>Foo</div>);
elements.push(<div>Bar</div>);
return elements;
}
So basically you can return array of children.
You can just return the two elements in the render method instead of declaring them and return them directly. Like this
render() {
return (
<div>
<div>Foo</div>
<div>Bar</div>
</div>
)
}
Extending on #Martin's answer above: If you are starting with latest version of React you should try and use React.Fragment as grouping element. Here is the reactjs documentation for it: https://reactjs.org/docs/fragments.html
There is also a shorter syntax for React.Fragment which is <>{elements}</>. However support for short syntax is not fully available yet.
Here is a codepen link for problem you are trying to solve: https://codepen.io/bdevapatla/pen/QxaKEq

Categories