How do i get refs value from dynamically generated array in React - javascript

I got my data from firebase, looped through it and displayed it on the frontend. Now I am trying to get the refs value of the already displayed value when I click on it. For example, when I click on Dino, i should be able to see the value 'Dino' on my console tab of Chrome browser.
Here is a link to the picture of the array list displayed on react frontend
<ul>
<li onClick={this.handleSubmit}>
{
Object.keys(this.props.group).map(function(keyName, keyIndex) {
return(
<div key={keyIndex}>{keyName}</div>
)
})
}
</li>
</ul>

Assuming that those "dino, magic & muu" are the keys in this.props.group you need to add an onClick handler to that div, so:
<div key={keyIndex} onClick={() => console.log(keyName)}>{keyName}</div>

You'll need to bind a click event to each div within the li. I would actually rewrite it like so:
<ul>
{
Object.keys(this.props.group).map( (keyName, keyIndex) => {
return(
<li key={keyIndex} onClick={this.handleSubmit.bind(this, keyName}>
{keyName}
</li>
)
})
}
</ul>
Then your handleSubmit function will get the keyName as a param:
handleSubmit(keyName){
// Do something...
}

Related

React - map over actual HTML children wrapped in HoC

I have a Component that renders all the children passed to it as list elements. For example:
// more or less the logic of my component
const ListifyChildren = (props) => {
return <ul>{props.children.map(element => <li>{element}</li>)}</ul>
}
// example use
<ListifyChildren>
<div>Some component</div>
<div>Some other component</div>
</ListifyChildren>
Would produce
<ul class="listify">
<li class="listify-list-item">Some component</li>
<li class="listify-list-item">Some other component</li>
</ul>
But the problem is I want to be able to use HoC's that return a list of components and to treat those components as children of my actual list. For example:
const ReturnSomeStuff = () => {
return [someArray].map(element => <div>{element}</div>
}
<ListifyChildren>
<ReturnSomeStuff/>
</ListifyChildren>
//what I get:
<ul class="listify">
<li class="listify-list-item">
<div>something</div>
<div>something</div>
<div>something</div>
</li>
</ul>
//what I want to get:
<ul class="listify">
<li class="listify-list-item">something</li>
<li class="listify-list-item">something</li>
<li class="listify-list-item">something</li>
</ul>
How can I make sure that my component maps over actual html children, not the function calls passed to it?
You can use Fragment to do it: https://reactjs.org/docs/fragments.html
const ReturnSomeStuff = () => {
return [someArray].map(element => <>{element}</>
}
I have found the answer: the key is referring to child elements via React.Children API rather than simple props.children - it returns the list of rendered elements.

How to send unique value to function from onClick in a mapping loop

I am learning React. I have an array in my state which I am mapping through to render each value of the array on its own button. When the user clicks one of those buttons, I want to call a function to show some info specific to that button (the button represents a specific customer order). I tried to set state in the onClick event, but I got an 'Maximum update depth exceeded' error. If there is a way to set state from the onClick, that would solve my problem as I could just set the value of item of the particular button clicked to state and use it later. My other thought is to send the item to the showInfo function...however, I don't even know if that is possible. How can I call the same function from this list of buttons, and make the outcome unique to the button?
showInfo = (e) => {
}
componentDidMount() {
this.showAllOrders();
}
render() {
return (
<div>
<h1>Hello from past orders!!!</h1>
<ul id="orderList">
{this.state.orderDates.map((item =>
<li><button onClick={this.showInfo} key={item}>{item}</button></li>
))}
</ul>
</div>
)
}
}
You could provide the function showInfo with info about the button via params.
So that it would be onClick={() => this.showInfo(item)}
Use an inline arrow function as a callback to your onClick and pass the data you want.
...
showInfo = (item) => {
console.log(item);
}
...
render() {
return (
<div>
<h1>Hello from past orders!!!</h1>
<ul id="orderList">
{this.state.orderDates.map((item =>
<li><button onClick={() => this.showInfo(item)} key={item}>{item}</button></li>
))}
</ul>
</div>
)
Also, never setState in your render method and thats why you got max depth error in your earlier try.

How to wrap HTML in JavaScript so as to iterate through a dictionary and add to a flex container?

I have this code:
<ul className="flex-container"> {
Object.keys(this.state.filestest).forEach(function(key) {
<div className="Tile">
*do stuff
</div>
});
}
</ul>
"filestest" is a String to String dictionary. All I want to do is be able to iterate through filestest, and add a div with className "Tile" for each item in the dictionary. The above code I wrote gives an error on the semi-colon, and other ways I try to write it doesn't work. I think this involves jQuery or something but I'm not familiar with jQuery. (I also need access to both the dictionary's keys and values).
In reactjs you'd do something like this (note the map instead of forEach):
// inside your react component:
render() {
return (
<ul className="flex-container"> {
Object.keys(this.state.filestest).map(function(key) {
return (<div className="Tile">
{key}
</div>)
});
}
</ul>
)
}

How to open a modal inside a rendered list in Vue?

I am rendering a list, and have a button that says "Expand". I want that when this button is clicked, it opens a modal with content that is fetched.
I'm trying to render the name inside the data, the same way I'm (correctly) rendering the date property. This can be seen in the following code:
<li v-for="data in tableData" v-bind:key="data">
<button v-on:click="openModal()">{{data.date}}</button>
<sweet-modal ref="modal">{{data.name}}</sweet-modal>
</li>
And the function that opens the modal looks like this:
openModal(){
// let vc = this; I have also tried calling vc.$refs.modal.open()
this.$refs.modal.open()
}
I'm getting a this.$refs.modal.open is not a function and I suspect that it is because this must be used in some clever way in the function that opens the modal.
I think the main issue is that you're rendering a modal component for each list item, which might not be what you want.
What you could do instead is to declare the modal outside of any other element and when you click a list item, you'd store that item in a variable and then you open the modal which will show the contents of that variable.
<template>
<sweet-modal ref='modal'>
{{crtSelectedItem.name}}
</sweet-modal>
<li v-for="data in tableData" v-bind:key="data">
<button v-on:click='openModal(data)'>{{data.date}}</button>
</li>
<!-- ... -->
</template>
export default {
data: () => ({ crtSelectedItem: null }),
methods: {
openModal (item) {
this.crtSelectedItem = { ...item };
this.$refs.modal.open();
}
}
}

reactjs parse child state to parent

i want to parse data from child to parent i have try solution from question
How to parse data from child to parent using reactjs?
I print that state and what appears is the state of the previous action, not the state of the last action
I tried to implement this to bring up content based on the menu that was clicked
example:
i have 3 menu
- A
- B
- C
when i click first time at the menu, for example A. the state in console is '', Then Second time i click B, the state in console is A
this is my code
PARENT
changeMenu= (menu) =>{
this.setState({
menu: menu
});
console.log('menu',menu); // Show State
}
render(){
return (
<LeftMenuMycommission active="0" menu = {(value) => this.changeMenu(value)}/>
CHILD
menuClick = (menu_name, active) =>{
this.setState({
menu: menu_name,
})
this.props.menu(this.state.menu);
}
render (){
render (
<ul>
<li ><a onClick={this.menuClick.bind(this, "A")}><i className={"fa fa-circle"}></i> A</a></li>
<li ><a onClick={this.menuClick.bind(this, "B")}><i className={"fa fa-circle"}></i> B</a></li>
<li ><a onClick={this.menuClick.bind(this, "C")}><i className={"fa fa-circle"}></i> C</a></li>
</ul>
Can anyone help me to find the problem?
Any help would be appreciated thank you :)
It's not guaranteed that state is updated immediately. You would need to use callback function and then call your parent method to pass the child component state to the parent correctly:
menuClick = (menu_name, active) =>{
this.setState({
menu: menu_name,
}, () => {
this.props.menu(this.state.menu);
})
}
Or, componentDidUpdate will do the same job:
componentDidUpdate() {
this.props.menu(this.state.menu) // only called after component is updated
}

Categories