useState set method for modal not updating - reactjs

I am trying to build a simple todo list. Basically there is a list of items. When the user clicks the 'edit' button on an item, selectedTodoItem is updated. Then a modal is shown which uses selectedTodoItem as prop.
I am also using ant.design library for the list.
Here is my code (with irrelevant bits left out):
const [selectedTodoItem, setSelectedTodoItem] = useState(selectedTodoList.items[0]);
const editItemHandler = (item) => {
setSelectedTodoItem(item);
dispatch(toggleEditTodoItemModalVisible());
}
return(
<List
className="whitebg listItems"
datasource={selectedTodoList.items}
renderItem={(item) => (
<TodoItemInList item={item} editHandler={editItemHandler} />
)}
/>
<TodoItemEditModal item={selectedTodoItem} />
);
<TodoItemInList> is basically a label and some buttons, one of which calls editHandler(item).
Here's a screenshot so you can get a better idea:
The problem is, when I load the page and click edit (blue, don't mind the delete icon) on an item, say 'Foundation', the edit modal loads fine. But when I click on another blue button, the modal still shows 'Foundation'. No matter what button I click, the modal only shows the first clicked item. It seems like selectedTodoItem is updating though, according to console.log(), but the modal's prop doesn't update with it.
Any nudge in the right direction would be much appreciated.

Related

How to get previous clicked element on any click event in Reactjs?

I am trying to make an single selection in my app. I have a grid and inside it some images. When I clicked an image its parent which is a div background color change to red. I describe this event it is selected. I want to make deselect previous item when click any where. if clicked image is one of my item then new item should be selected and previous should be unselected. if clicked element is not one of my items just previus should be unselected. When I select an item then clicked one of the others it is working. However when I selected an item then click out of my items it is not working. In this stuation my prevClickedElement parameter refers to previous of previous clicked element. And I have no idea why state empty when update it in clickElement in context and in removePrevSelectedSquare in Piece component. Because of my app has multiple components and images I added to here. I am not sure this is the correct way. Because when I select an item component created items count times in this case 15. This is a performance problem?
I believe a good approach would be creating a component global state to save the current element unique id and creating a function to set the element id when it is clicked. After that you can create a function that reset this state whenever it is called and implement this function as an DOM event in a superior div, the parent of the images. Here is the ideia in form of a code snippet:
import React from 'react';
function Stackoverflow(props) {
const [selectedPicture, setSelectedPicture] = React.useState(null);
function resetSelectedPicture() {
setSelectedPicture(null)
}
return (
<div onClick={resetSelectedPicture}>
{pictures.map((picture, index) => {
const {id, src} = picture;
return (
<>
<img
src={src}
key={index}
id={id}
className={
selectedPicture.id === id
? 'selected-picture'
: 'unselected-picture'
}
onClick={setSelectedPicture(
() => picture
)}
/>
</>
);
})}
</div>
);
}
export default Stackoverflow;

Update array of items with help of modal input in React

I didn't find any suitable answer for this question. Here is what I am looking for.
I have lists of menus items coming from the state array variable (https://i.imgur.com/FzD0sol.png).
I have an add button which opens a modal. Modal includes an input field. (https://i.imgur.com/6DCZhoj.png)
The final result would be when some click adds button of modal, its field values updated in menus state array. which further updates the menus list on UI.
I able to made all these UI. But I didn't have any idea how can I pass my data from modal input to menus list. Here is codesandebox link of the same problem (https://kx6yr.csb.app/).
There is a way to solve your problem :
You have to give a callback props to your Modal component. As it, The modal will be able to add an item.
There is the codesandBox : https://codesandbox.io/s/friendly-boyd-ptxem
So this is one way to do it, in your modals add this onAdd prop:
<AddModal
heading="Add Food"
modalId="addFood"
inputName="addFood"
onAdd={(textEntered) => { alert(textEntered); }}
ref={this.foodModal}
/>
<AddModal
heading="Add Drink"
modalId="addDrink"
inputName="addDrink"
onAdd={(textEntered) => { alert(textEntered); }}
ref={this.drinkModal}
/>
And within the modal component, call this handler passing the input value:
<button
type="button"
onClick={this.props.onAdd.bind(this, this.state.item)}
className="golden-button-op"
style={{ margin: "0px" }}
>
Add
</button>
Hope it helps!

React Mapbox Extra Button Doesnt Work Inside Popup

I am working with mapbox react gl - It is working pretty nice so far... except one thing.
The user can add their hometown location to the map. When the hometown location appears, it can be clicked to view a popup. I want the user to be able to remove the location from the map from inside the popup - So I added a function that removes the location from the database when a button is clicked. The problem is when the button is inside the popup the function doesn't fire - and I have no idea why.
I have messed with the z index of the button but it seems like whenever the button is clicked, the onClose function is being called instead of my handleDeleteHome function...
Edit* If I remove the onClose function, the handleDeleteHome function fires.
Any help is appriciated! Thanks!
{selectedHome && (
<Popup
latitude={bandLocation[0]}
longitude={bandLocation[1]}
onClose={() => {setSelectedHome(null)}}
offsetLeft={23}
offsetTop={-10}
>
<div>
<h4>Home Town</h4>
<Button
onClick={(e) => {
e.preventDefault()
handleDeleteHome()
}}
color="danger">x</Button>
</div>
</Popup>
)}
Alright! Figured it out - If anyone else needs to know:
You need to add closeOnClick={false} to the popup!

Dynamic Popover in ReactJS

I'm fairly new to React and I'm using the Ant Design framework (https://ant.design/).
I have a table list of items that I'm looking to have a button on each so that when it is pressed additional information about that row becomes available (which is a secondary API call specific to that row).
I'm trying to use a popover but I'm noticing that the popover wants the text before being rendered which is a problem since I don't have that information until the second API call. The best idea I've come up so far is to have the button press trigger the api call and then the state is updated but that creates a funky experience (as it is update after the popover is already opened - after starting with the previous rows information). It isn't a huge amount of time but it still isn't an ideal experience.
This is what I have so far:
<Popover content={this.contentSec([record['section']])} title=
{record['section']} trigger="click">
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
</Popover>
this.sectionAttributes triggers my fetch request. and this.contentSec does the formatting on the existing popup (see below).
contentSec(props) {
const listItems = this.state.attributes.map((item) =>
<li>{item}</li>
);
return <div><ul>{listItems}</ul></div>
}
Any ideas of a better way to handle this so that there isn't that buggy delay when clicking the button for the popover?
Thanks.
As the content is populated after the second api call, You can send two props content which can be empty string or any default value and loading variable as true on click. Once you have the data after the API call you can send the updated props ie content with actual text and loading as false and finally handle your logic and state update in componentwillrecieveprops() in the popover component.
You can use the loading prop to switch from a loader initially to the actual content.
Write a condition to check if the response from this.sectionAttributes(record['section'] is true, if it is true then
<Popover content={this.contentSec([record['section']])} title=
{record['section']} trigger="click">
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
</Popover>
else simply use
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
For the first time user clicks on button, the component rerenders and state gets updated, so when it rerenders you can see popover as the if condition satisfy.

How to change URLs (but not entire view) when clicking on a modal with Material-ui and react-router 4?

I have an app using a material ui List with ListItems.
I want for users to be able to click on a ListItem and have it open a Modal or a Collapse to give more info about the ListItem. I want the view to stay the same (overall), albeit with a new url that links to that Modal or Collapse.
Right now, all I can get is that the user clicks on the ListItem and it opens an entirely new view.
I want to have the ListDetails or ListItem details be shown in a collapse or modal (or some ui that is on that same page) and be linkable (have a url)
Code:
// List
<List>
<Collapse>
<ListItem <Link to={`/listitem/${listitem.id}`}> />
<ListDetail />
</Collapse>
<ListItem />
<Modal><ListDetail /></Modal>
</List>
// Router
<Route path="/list/:id" render={({ match }) => <ListDetail params={match.params} />} />
This goes to an entirely new page. How to wire it up to so that I can show ListDetail within the same page?
How to set up the components/routing to change urls but just change the UI (and not render an entirely new page?
Do not put <Link to={'/listitem/${listitem.id}'}> there. Instead put an on-click handler with on-click function as this.props.router.push('/bar'). This will cause the route to change.
And when modal is false you can revert the url to previous url using the same method.

Resources