Stop Render of Reactjs Component? - reactjs

I am wondering what is best practice. Should you let all components render or should you stop them from rendering? Say I have a delete modal that only gets shown on a click.
Should I put in my render of my modal
render() {
// if something return false to stop rendering
return ( )
}

Design your DeleteModal component so that in its render() method it renders the required UI, always. Then in the parent component, the one that uses the dialog, you conditionally show/hide it:
render() {
return (
<div>
some content here
...
{showDeleteModal ? <DeleteModal /> : null}
</div>
);
}

Related

Rendering Child Component after Parent in React

I am rendering a child component of a parent component. The text inside the render method of the child component is being rendered, but the map function is not being called on the JSON array I have in the child component. I used console.log and the array has the right values in it. Here is the render function of the child component:
console.log("rerender: " + JSON.stringify(this.state.myDropdownMessages));
this.state.myDropdownMessages && console.log("DID THIS!");
//}
return (
<>
TESTING 1234---does render
{this.state.myDropdownMessages && this.state.myDropdownMessages.map((oneMessage) =>
{
{/*let blueDotDisplay = false;
if (oneMessage.hasBeenViewed = "false"){
blueDotDisplay = true;
}*/
}
<>
Inside map function--doesn't render
<img src={oneMessage.posterprofilesrc} className='OneHeaderMessageProfilePic' />
<div className="OneHeaderMessageRightDiv">
test again
<div className="OneHeaderMessageInfo">
<div className="OneHeaderMessageNameDiv">
{oneMessage.postername}
</div>
</div>
<div className="OneHeaderMessageTimeDiv">
{oneMessage.time}
</div>
</div>
<div display = {(oneMessage.hasBeenViewed == 'false') ? 'block' : 'none'} className="OneHeaderMessageBlueDot" id={'OneHeaderMessageBlueDot' + oneMessage.id}>';
</div>
</>
}
)}
The child component is rendered on the click of a button from the parent component. It renders the code before the map--"TESTING 1234"--but doesn't render the code inside the map function even though the map function is loaded. It even prints out on the console right before the render function is supposed to return that the array is fully loaded with the right values. Is the problem that the parent component doesn't rerender the child component once the data is loaded in the child component? I tried calling the parent render function from the child but it didn't work. Neither did calling child component's render function. Thank you very much for your help.
Make sure to return from the mapping loop, you are looping but never returning hence no react node are being rendered.
myArray.map(item => {
return (<div> Hello World </div>)
})
Just add return to your map function or just remove curly brackets ...myDropdownMessages.map((oneMessage) => <> //..some code.. </>
or
...myDropdownMessages.map((oneMessage) => { return (<> //..some code.. </>)}

React Button Click Hiding and Showing Components

I have a toggle button that show and hides text. When the button is clicked I want it to hide another component and if clicked again it shows it.
I have created a repl here:
https://repl.it/repls/DapperExtrasmallOpposites
I want to keep the original show / hide text but I also want to hide an additional component when the button is clicked.
How to I pass that state or how do I create an if statement / ternary operator to test if it is in show or hide state.
All makes sense in the repl above!
To accomplish this you should take the state a bit higher. It would be possible to propagate the state changes from the toggle component to the parent and then use it in any way, but this would not be the preferred way to go.
If you put the state in the parent component you can use pass it via props to the needed components.
import React from "react";
export default function App() {
// Keep the state at this level and pass it down as needed.
const [isVisible, setIsVisible] = React.useState(false);
const toggleVisibility = () => setIsVisible(!isVisible);
return (
<div className="App">
<Toggle isVisible={isVisible} toggleVisibility={toggleVisibility} />
{isVisible && <NewComponent />}
</div>
);
}
class Toggle extends React.Component {
render() {
return (
<div>
<button onClick={this.props.toggleVisibility}>
{this.props.isVisible ? "Hide details" : "Show details"}
</button>
{this.props.isVisible && (
<div>
<p>
When the button is click I do want this component or text to be
shown - so my question is how do I hide the component
</p>
</div>
)}
</div>
);
}
}
class NewComponent extends React.Component {
render() {
return (
<div>
<p>When the button below (which is in another component) is clicked, I want this component to be hidden - but how do I pass the state to say - this is clicked so hide</p>
</div>
)
}
}
I just looked at your REPL.
You need to have the visibility state in your App component, and then pass down a function to update it to the Toggle component.
Then it would be easy to conditionally render the NewComponent component, like this:
render() {
return (
<div className="App">
{this.state.visibility && <NewComponent />}
<Toggle setVisibility={this.setVisibility.bind(this)} />
</div>
);
}
where the setVisibility function is a function that updates the visibility state.

How to replace a component with another one upon event (button click) in react js

I have a long list of data display divided into blocks with an edit button on side of each block, like this:
Whenever the edit button is clicked, i need to replace the display component with edit component, replacing the text with form like this
what would be the best way to do this.
I have tried putting the components inside state as list and replacing Display component with Form Component, when Edit is clicked
so instead of returning this from render():
return(
<Display />
);
Now i am returning:
return(
{this.state.components[0]}
);
and when button is clicked doing this
this.setState({components:[<EditForm />]})
It works but i was wondering is storing Component and JSX inside state a good idea/ professional practice?
you could do something like this:
use a variable in state for knowing edit is clicked or not
state={
isEdit:false,
}
on click of edit:
this.setState({isEdit:true})
in render() use conditional rendering:
render(){
return(
<div>
{(!this.state.isEdit) ? <Display /> : <EditForm />}
</div>
)
}
I would hold in state just a Boolean for showing the edit form or the display and toggle this on button click.
Then in you render method just a simple if statement to choose what to render e.g.
render() {
if (this.state.edit) return <EditForm />
return <Display />
}

Is it okay to call setState on a child component in React?

I have some text. When you click on that element a modal pops up that lets you edit that text. The easiest way to make this work is to call setState on the child to initialise the text.
The other way, although more awkward, is to create an initial text property and make the child set it's text based on this.
Is there anything wrong with directly calling setState on the child or should I use the second method?
Although it is recommended to keep the data of your react application "up" in the react dom (see more here https://reactjs.org/docs/lifting-state-up.html), I don't see anything wrong with the first aproach you mentioned.
If you have to store data that is very specific of a child I don't see anything wrong in keep that information in the child's state.
It seems that your modal doesn't need to have its own state, in which case you should use a stateless React component.
This is one way of passing the data around your app in the React way.
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
initialText: "hello",
}
this.saveChildState = this.saveChildState.bind(this);
}
saveChildState(input) {
console.log(input);
// handle the input returned from child
}
render() {
return (
<div>
<ChildComponent
initialText={this.state.initialText}
save={this.saveChildState}
/>
</div>
);
}
}
function ChildComponent(props) {
return (
<div>
<input id="textInput" type="text" defaultValue={props.initialText}>
</input>
<button onClick={() => props.save(document.getElementById('textInput').value)}>
Save
</button>
</div>
)
}
Maybe I am misinterpreting your question, but I think it would make the most sense to keep the modal text always ready in your state. When you decide to show your modal, the text can just be passed into the modal.
class Test extends Component {
constructor() {
this.state = {
modalText: 'default text',
showModal: false
}
}
//Include some method to change the modal text
showModal() {
this.setState({showModal: true})
}
render(
return (
<div>
<button onClick={() => this.showModal()}>
Show Modal
</button>
{ this.state.showModal ? <Modal text={this.state.modalText}/> : null }
</div>
)
)
}

Changing background-image after onClick event in ReactJS

I have a component, let's say it looks like this:
return(
<div id="container"></div>
)
From the beginning it's background image is already set, let's say
#container{
background-image: url('./assets/container.jpg');}
Now I want to add another element inside the container div that will have onClick event firing function, that will do other things + changing the parent's background-image. Dummy code would be:
handleOnClick(){
doOtherStuff();
document.getElementById('container').style.backgroundImage = "url('./assets/container2.jpg')"}
return(
<div id="container">
<div onClick={()=> handleOnClick()}
</div>
)
Problems are:
It doesn't work, it changes background to blank screen,
After I leave the component and go back to it, it reverts to the old background. Is there any way to avoid that without having the background linked with state? I already have a lot of things in store and it will start to get messy real soon if I start adding more styles to it.
This is doable by giving your child the ability to change the state in your parent and holding that logic there. Also, it's much better to control your background shift by using this.setState. Just make it a boolean that controls which CSS id to use.
class Parent extends Component {
constructor() {
super()
this.state = {
defaultBackground: true
}
}
toggleChildBackground() {
const newBackground = !this.state.defaultBackground
this.setState({defaultBackground: newBackground})
}
render() {
return (
<div>
<Child
defaultBackground={this.state.defaultBackground}
toggleChildBackground={this.toggleChildBackground.bind(this)}
/>
</div>
)
}
}
class Child extends Component {
handleClick() {
this.props.toggleChildBackground()
}
render() {
return (
<div id={this.props.defaultBackground ? 'id1' : 'id2'}>
<button onClick={this.handleClick.bind(this)}>
change background
</button>
</div>
)
}
}

Resources