Many fat arrows in a row in Javascript? [duplicate] - ecmascript-6

This question already has answers here:
What do multiple arrow functions mean in JavaScript?
(7 answers)
Closed 2 years ago.
I came across this code in the documentation for an NPM lib I was considering.
Coud someone attempt to explain to me what at least the first line is doing? It appears that the 3 => bits imply that these functions all return functions.
I consider myself (perhaps wrongly) passably good at javascript. The way thisis put together seems overly convoluted, at least clear obvious to me. I suppose if I could a bit more if tried hard enough, but something about this just feels overly confusing, so I moved on to another library.
The first line, and order of assignment, where functions start and stop is the least for me.
const withTimer = timerProps => WrappedComponent => wrappedComponentProps => (
<Timer {...timerProps}>
{timerRenderProps =>
<WrappedComponent {...wrappedComponentProps} timer={timerRenderProps} />}
</Timer>
);
class TimerWrapper extends React.Component {
shouldComponentUpdate() {
return false;
}
render() {
return (
<div>
<div>Simple text</div>
<Timer.Consumer>
{() => this.props.timer.getTime()}
</Timer.Consumer>
</div>
);
}
}
const TimerHOC = withTimer({
initialTime: 5000,
})(TimerWrapper);
<TimerHOC />

It is essentially this
function withTimer(timerProps) {
function withWrappedComponent(WrappedComponent) {
function withWrappedComponentProps(wrappedComponentProps) {
return (
<Timer {...timerProps}>
{(timerRenderProps) => (
<WrappedComponent {...wrappedComponentProps} timer={timerRenderProps} />
)}
</Timer>
);
}
return withWrappedComponentProps;
}
return withWrappedComponent;
}
If that helps
Alternatively as a sort of intermediary between both forms, it is like this
function withTimer(timerProps) {
return function (WrappedComponent) {
return function (wrappedComponentProps) {
return (
<Timer {...timerProps}>
{(timerRenderProps) => (
<WrappedComponent {...wrappedComponentProps} timer={timerRenderProps} />
)}
</Timer>
);
};
};
}

Related

How to filter the props.children

I use props.children in function component like below which is working fine as in all children renders fine in UI.
function Footer(props: FooterProps) {
return (
<div>
{props.children}
</div>
);
};
However, I need to filter the props.children based on some properties of child and put them in different div. There are no errors in console, but child components does not render.
function Footer(props: FooterProps) {
return (
<div>
{props.children?.map(child => {
if (child.align === "right") { //no probs with this condition, code executes as expected.
<div> // grouping into another div
{child}
</div>
}
else {
{ child }
}
})}
</div>
);
};
Any idea what could be wrong here?
You aren't returning anything in your map callback, it's becoming an array of undefined which React is designed not to render anything for. If you wrap your two intended values in return statements it should work as intended.
Here's what that would look like:
function Footer(props: FooterProps) {
return (
<div>
{props.children?.map(child => {
if (child.align === "right") { //no probs with this condition, code executes as expected.
return (
<div> // grouping into another div
{child}
</div>
);
}
else {
return child;
}
})}
</div>
);
};
I'm not sure if this is really the correct way to do this, generally speaking I'd discourage changing a child directly in this way after receiving it and looking for a more compositional approach, but in the case that you do need to do so, you might should be using the React.Children.map method: https://reactjs.org/docs/react-api.html#reactchildrenmap

Ionic React component not updating/rendering image

I am using Ionic React to develop a web app. Since I am new to this I am running into a few issues here and there. One of which I haven't been able to fix.
I have a TeamLogo component that is supposed to display an image after fetching it from my rest api. However the view / image doesn't seem to update properly every time. So in some cases I just get the default logo. If I route/switch to a different page and then back it will render the correct logo. As soon as I reload the page it is back to the default logo. What am I doing wrong? I have tried without a default logo, then it's just blank and nothing shows even in html. So the default logo is just for visualization/debugging.
I have had this issue in the past but I was able to fix it by wrapping the TeamLogo inside a <React.Fragment>. However this time it won't work and I really have no clue why it even worked in the past. Why isn't it rerendering?
My code looks like this:
export const TeamLogo: React.FC<TeamLogoProps> = ({teamId, width}) => {
const [teamData, setTeamData] = useState<any>(null);
console.log('trying data from ' + teamId);
useEffect(() => {
if (!teamData || teamData.id != teamId) {
fetchTeam(teamId, (data) => {
setTeamData(data);
console.log('fetched data from ' + data.name + " " + teamId);
});
} else {
console.log('Had existing data for ' + teamData.name+ " " + teamId)
}
});
if(teamData != null) {
return (
<img className={teamData.name} width={width + "px"} src={"data:image/png;base64," + teamData?.baseLogo}/>
);
} else {
return <img className="NRG Esports" src="data:image/png;base64,defaultBase64..." width="50px"/>
}
};
And I am using it like this:
function getScoreTeamNameEntry(showScore: boolean, team: any) {
return (
<div className={(showScore ? "" : "hidden-keep-size ") + "name-entry"}>
{team.id ? (<Link className="float-right" to={"/team/" + team.id}>
<React.Fragment><TeamLogo width={50} teamId={team.id}/></React.Fragment>
<IonLabel className={"color-contrast"}>{team.name}</IonLabel>
</Link>) : <IonLabel className={"color-contrast"}>{team.name}</IonLabel>}
</div>);
}
Any help is appreciated!
EDIT:
I have played around with it a bit and was able to bypass the issue, but it's still very strange. Here is what I found out:
<div className="participant winner">
{
getPlaceholderEntry(teamData, id)
}
</div>
I am now passing the id instead of the teamData only so the logo can load from the sole team id and does not have to wait for the teamData to load.
Now getPlaceholderEntry just does this:
function getPlaceholderEntry(team: any, teamId: any) {
console.log("Placeholder");
return (
<React.Fragment>
{
getScoreTeamNameEntry(true, team, teamId)
}
</React.Fragment>)
}
However replacing the getPlaceholderEntry call with a direct
<React.Fragment>
{
getScoreTeamNameEntry(true, team, teamId)
}
</React.Fragment>)
for some reason does not render/update it yet again.
Also adding any sort of condition like
<div className="participant winner">
{
teamData && getPlaceholderEntry(teamData, id)
}
</div>
breaks it yet again. Any idea what's going on?
useEffect(() => {
... original code
},[teamData,teamData.id]);
you need to add the dependencies on the useEffect so the component will rerender when the data changes
https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect

How to get multiple selected checkbox item from multiple checkbox list in angular

i have minimal reproduce here https://stackblitz.com/edit/angular-uwfsyv?file=app%2Fapp.component.html, there i have 2 array,checkboxesDataList and checkboxesDataList2 i successfully get the checked label from checkboxesDataList but that's just for an example.
but what i wanted to get in my project is similar to checkboxesDataList2 inside here i have object question and checkboxesDataList don't have that so this function
fetchSelectedItems() {
this.selectedItemsList = this.checkboxesDataList.filter((value, index) => {
return value.checked;
});
}
won't work immediately if i change this.checkboxesDataList to this.checkboxesDataList2 how can i make it work?
do you want to has a function like?
getDataChecked()
{
return this.checkboxesDataList2.question
.map(x=>x.options.filter(o=>o.checked))
.reduce((acc, value)=>[...acc,...value])
}

React + CSS Grid + MongoDB?

Im creating a webpage in which users can post stuff to a "bulletin board". These posts are gonna be styled as boxes, and I want to add them to a grid layout. This is my code:
import React from 'react';
//import Gallery from "./components/gallery.component"
function App() {
state = {
posts = [];
};
componentDidMount = () => {
this.getPosts();
};
getPosts = () => {
axios.get('(server)')
.then((response) => {
const data = response.data;
this.setState({ posts: data });
})
}
displayBlogPost = (posts) => {
if (!posts.length) return null;
return posts.map((post, index) => (
<div key={index} className="post__display">
<h3>"name " + this.state.name </h3>
</div>
));
};
render() {
return (
<div className="App">
<header className="container">
Logo
</header>
</div>
<div className="gallery">
{this.displayBlogPost(this.state.posts)} </div>
)
}
}
export default App;
Im a little unsure of how to work on the grid. Ive been looking into the CSS Grid documentation and I was wondering if it would be enough to keep my code as is and create a css file with an id #gallery that sets the attributes of the grid (display, grid-gap, repeat, etc). Would this be enough, or will I have to change my displayBlogPost function. I'm worried that the approach will consider gallery just containing one element and therefore there wont even be a grid.
Would appreciate some clarification and suggestions, I tried to find examples online, but none seemed to use react, mongodb, and css grid.
Its also hard because Im a newbie to React and MongoDB and JavaScript in general, but this project is for a hackathon and Im on a time crunch
Even though the post contains only one element the HTML DOM would show the grid in itself.
Yes, you can create a separate CSS file and include the req. CSS there.
Also, "name " + this.state.name you have not defined the state "name", how are you expecting for a display of value there?

Angular 6 - How to stop infinite polling in subscribe()

So I want to show an icon based on whether or not the number of projects in my list is > 3. I am using this getProjects() function that I need to subscribe to in order to get the data. I am setting a boolean when I subscribe that checks the number of projects in the list, then in my HTML, I use a ngIf to show the icon based on the boolean. I am able to get it to show correctly, however, I think I am constantly polling in my subscribe, and setting this boolean over and over again because it is making my webpage run really slow.
I have already tried the take(1) method which doesnt seem to stop the subscription, as well as set it to a "this.variable" scope inside my component. I am currently using event emitters however that is not working either.
This is my code so far,
Function that I subscribe to (in a different component):
getProjects(): Observable<ProjectInterfaceWithId[]> {
const organizationId = localStorage.getItem('organizationId');
return this.firestoreService.collection('organizations').doc(organizationId)
.collection('projects').snapshotChanges()
.pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data() as ProjectInterface;
const id = a.payload.doc.id;
return {id, ...data} as ProjectInterfaceWithId;
})),
map(list => {
if (list.length !== 0) {
this.buildProjectLookup(list);
this.projects = list;
return list;
}
})
);
}
Function that i use to get the data and set the boolean:
#Input() toggle: boolean;
#Output() iconStatus = new EventEmitter();
displayIcon() {
this.projectService.getProjects()
.pipe(take(1))
.subscribe(
list => {
if(list.length >= 3){
this.toggle = true;
this.iconStatus.emit(this.toggle);
}
});
}
HTML:
<i *ngIf="displayIcon()" class="material-icons">list</i>
Is there any way for me to literally just check the list length once so I don't get caught in this subscription loop? Thank you in advance!
It looks like it could be happening due to the ngIf referring to the displayIcon() method.
Every time change detection runs within your component, this method will be called. If your component is using default change detection, this will be very often.
see https://blog.angular-university.io/how-does-angular-2-change-detection-really-work/ for more
One way this could be fixed is by making the ngIf refer to a variable instead.
For example, you could set a projects$ observable using
this.projects$ = this.projectService.getProjects()
.pipe(
take(1),
tap(projects => this.iconStatus.emit(projects.length >= 3))
);
This observable should likely be instantiated in your ngOnInit() method.
Then in your template you can use
<i *ngIf="(projects$ | async)?.length >= 3" class="material-icons">list</i>