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.. </>)}
Related
Here is my component:
export default function Card({ title, myFunc }) {
return (
<div>
<h2>{title}</h2>
<button onClick={myFunc}>click to add</button>
</div>
);
}
and here is my app (its parent) where I used it:
function App() {
return (
<div className="App">
{data.map((item) => {
return (
<Card
key={item.id}
title={item.title}
myFunc={() => {
alert('hi');
}}
/>
);
})}
</div>
);
}
As it can be seen I implemented the logic,which shows 'hi' by clicking on the button, outside my component. This is while I could have implemented the above logic just inside my component to do the same thing without any change in my app code just like this:
export default function Card({ title }) {
return (
<div>
<h2>{title}</h2>
<button
onClick={() => {
alert('hi');
}}
>
click to add
</button>
</div>
);
}
What I'm trying to figure out is when should I implement my logic inside the component and when outside it? Is there any rules or something about it or it does not matter at all?
If Parent need information for working and Child update this information, you must place information and function in Parent and give a callback function to the Child.
If an other Child of Parent need the value update by an another Child, you must create value and function in Parent, and give value and callback to Child.
Else, if Parent don't care about the Child to do and the value is manipulate, Child be work alone.
In you're example, Child need title from Parent because Parent have the Array with title so clearly, it's normal usage. But the function alert('hi') can be directly on your child, because every Card do the same things and Parent don't care about what happen after alert('hi').
I have a React component that is used to layout its children according to their key. Here is what it looks like:
<Container focusedChildKey={this.state.focusedChildKey}>
<Child key="child1" />
<Child key="child2" />
<Child key="child3" />
</Container>
In the container, in the render function I do something simple:
let focused = null;
let normals = [];
React.Children.forEach(children, (child) => {
if (child.key === this.props.focusedChildKey) {
focused = child
} else {
normals.push(child);
}
});
return (
<div>
<div className="focusedChild", style={{ ... }}>
{focused}
</div>
{normals}
</div>
);
The problem I encounter is that whenever the focusedChildKey props changes on the Container, the focused child got unmounted and mounted again. Children in my case carry a lot of states that I lose every time one of the child get focused.
I read a lot but can't understand why it's re-mounting the whole component.
Using React, how can a child component be wrapped conditionally in another element if it is not returning null when rendered?
export const Parent = ({children}) => (
<div className="row">
{React.Children.map(children, child =>
<div className="col-6 col-s-4 col-md-3">
{child}
</div>
)}
</div>
);
This might be related to the discussions in React component children detect if empty / null before render however, none of the proposed approached seemed to work (ReactDOMServer.renderToStaticMarkup seem to have issues with SSR and React.isValidElement is persistently treating the component that returns null as a valid element).
I've got a feeling that this is sort of an anti-pattern, as it seems to be real hard to do. Only solution I can think of at the moment is moving the column div into the child component and clone a prop into the child to inform it that a wrapping column div is desired... Which seems way hacky.
If you don't want to use
const isChildNull = children => {
return !Boolean(ReactDOMServer.renderToStaticMarkup(children));
};
try with:
const isChildNull = children => {
return Boolean(children.type() === null); //--> will return the tag type
};
If child component receives props, don't forget to pass those props when calling type function:
const isChildNull = children => {
const {type, props} = children;
return Boolean(type(props)=== null);
};
EDIT: working example here: https://stackblitz.com/edit/react-a29daw
I have a small application when you open a tab the React Route redirects to the given component (container). And from the container i want to render the child components. I use the foreach loop to go through a list that has the props that need to be given to the child. However, the child doesn't get rendered.
I don't want to use map because i use libraries that depend on the list class.
render() {
return (
<div>
{this.state.list.ForEach((element) =>
<ChildComponent childName={element.name}
}
</div>
);
}
}
You are confusing Array.forEach with Array.map. forEach does not return anything. The correct way is:
<div>
{this.state.list.map((element, index) =>
<ChildComponent key={index} childName={element.name} />
)}
</div>
map converts the given element into another element, a component in this case. The result of calling map is an array of components that is then rendered. forEach always returns undefined therefore the result of your code is the same as writing:
<div>
{undefined}
</div>
Note that key is also necessary when rendering lists of components.
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>
);
}