ReactJS - render with default state - javascript

How can I rerender component with state from getInitialState()?
For example: https://jsbin.com/pajapoyipo/edit?html,output
In example code I click on the button, component Button change state and button is Yellow - its work, but when I click on another button I would like to clicked the button was yellow (its work), and the old button changed state and color to red (it doesn't work).

Avoid stuff like this:
childState.setState({klasa: "yellow"});
You should not be setting child state from the parent. State is internal to a component, it should only be changed by itself. Instead, the parent can re-render the child with different props.
If you want only one button to be active, then you have to have some piece of state that will only permit a single active button. Since children can't know about their fellow siblings, this piece of state must reside in the parent. I've called it activeBtn. If activeBtn is 1, then the first button appears yellow. This piece of state in the parent corresponds to the boolean property active in child. I've also defined a click handler in the parent to change the state. This click handler is passed down to each child as a prop.
If that doesn't make sense, the modified code should serve as a better explanation:
https://jsbin.com/filasisemu/1/edit?html,output

Related

How to use child component data in parent component? How to make a binding?

For example, we have one field Input, property 'currentNode' in child component and property 'activeElement' in parent component. Every time we change value in Input, it affects property 'currentNode'. And also, of course, parent component contains child component (I mean HTML).
So, I want that every time currentNode changes somehow, it affected activeElement, which's located in parent component.
Add (change)="" method into your Input field. Then Use #Output() to send the event on every change. While you emit currentNode in your parent. your parent function automatically calls then you can update your parent activeElement with the emitting value
click here to see How you can send data to your parent component

Update state only on OK, revert back to previous state on CANCEL

I have a react app similar to what is shown in this codesandbox link
https://codesandbox.io/s/eatery-forked-t44bx?fontsize=14&hidenavigation=1&theme=dark
Clicking the Menu at the bottom center of the page renders the MenuFilter component.
The way I have it now, checking the checkbox immediately updates the checked items. This is good from a user interface point of you.
User gets instant feedback on what he is clicking on (what is getting un-clicked if something is getting un-clicked).
The problem with though is that the OK/Cancel button loose there use. In other words, after making changes to the selection, if the user decides that we does not want any of these new selection & rather revert back to old selection (the one before the Menu button was clicked), he cannot do that because all the states have been updated (updating happens as the check boxes are being clicked).
How to update the state ONLY if OK (currently only CANCLE button is working, so you can consider that) button is clicked. However, the check-marks should none the less change as the user is clicking them.
Is there a way to do this other than creating a 'temporary' state (I don't want to do this) to update the visual changes & only when a button is clicked, the changes are done one the data.
You can change the checkedItems to a local state of the MenuFilter component, and pass it as an argument on onClick. That way, when you open the modal, the component mounts again and the state should return to its default.
Something like:
export const MenuFilter = ({ onClick, onCheck }) => {
const [checkedItems, setCheckedItems] = useState(["allItems"])
return (
<button onClick={() => onClick(checkedItems)}>Cancel</button>
)
}
Edit: You'll still need some sort of state to handle the data on the parent component, but you won't have to manually handle resetting the data.

React useEffect on dom element

Let's say I have two "buttons" (they're div elements with an onClick attached). Each one changes a product's price inside a div element.
How can I do something when that div was clicked, inside another component ?
Can I somehow put dom element to the dependencies array of an useEffect ?
for example:
useEffect(() => {
// Do stuff
}, [document.getElementById('div-that-shows-price')])
I tried the above, didn't work. I even tried it with .textContent, innerHTML, ....
I'm guessing I can't use ref because again, they're in different components. Or can I use a ref defined in a component from another one ?
I think you have to use useRef hook:
https://fr.reactjs.org/docs/hooks-reference.html#useref
The question is not clear. But from what I understand, why don't you pass price as props to another component? You can put product price in a parent component state and pass it as props (with updatePrice method) in both button components. Or use global state (redux).
I am guessing, what you building is basically counter, in one div you want count aka price to be able to incremented and decremented, and in the other div you would like to see the button click result. Since you're using React, this is achieved by useState() and just passing result prop from parent component div which would have the button to the child component div.

calling a method of a particular child ref in react when there are multiple components

I have a parent component which is a set of child filter menu components. Each child component has a group of radio buttons, and the buttons all determine whether they are checked via their state.
In the parent component, when there is at least one filter for which the user has made a selection, a list of buttons appears of the selected filter options.
When one of these buttons is clicked, it should call a function within that child component to reset its radio groups.
I have seen here and here how to call a function within a single child ref when that ref is known, but how would I accomplish this when the refs are generated in a loop, and I want to only to call the ref of the specific child component that matches the button that was clicked?
Here is the relevant [pseudo-code]:
//FILTERS.JS
{filters.map((filter, index) => {
return (
<FilterContainer
key={`filter--${filter.id}`}
//NEED UNIQUE REF HERE THAT I CAN CALL
/>
)
})}
handleClearSelectedFilter = ()=>{
this.[matchingFilterContainerRef].current.resetRadioGroup();
}
where matchingFilterContainerRef would be the dynamic ref I match to the button that was clicked for the corresponding filterContainer child component.
With hopes I understand your issue correctly, I would like to suggest a different approach.
In the parent component you have a state which hold the filters. each of these filters has its own set of values. The parent then maps over the filters and passes each FilterContainer the props it needs, like the values for it, and also a callback function to when there was a change.
According to the values, the FilterContainer knows how to render its radio buttons. Data is flowing from the parent to the child in a single direction.
Once a radio button is clicked, you will call the callback given by the parent with the filter field and current value, e.g. a gender radio button was clicked, you will call this.props.onValueChange('gender', 'female').
The parent will then receive the callback and set its filters state accordingly. The state changes, the filters get rendered again with the new data.
Hope this helps :)
You can do like this
{filters.map((filter, index) => {
return (
<FilterContainer
key={`filter--${filter.id}`}
ref={`ref_${filter.id}`}
//NEED UNIQUE REF HERE THAT I CAN CALL
/>
)})}
And when you want to access it:
this.refs[`ref_${filterId}`]
See more here reactjs-dom-dynamic-refs

Hide component when another identical component is shown with React

I have a list of items (ResultItem), which have a component inside (ResultTag) which when clicked, shows a tooltip above it (a HTML class is added to it and removed when clicked again, to hide it).
However, when I click on ResultTag, and then click on ResultTag in one of the ResultItem's below it, both show; how would I go about hiding all of the ResultTag's apart from the one I just clicked on, so that only one can show at a time.
Currently, in the ResultItem, I have an onClick function which sets the state showTooltip in the ResultTag to false/hidden (using props) whenever the user clicks anywhere within ResultItem and the ResultTag is visible. However, I need this to work across every ResultItem, which means working cross-component.
Here is some simplified code:
/* ResultTag */
showTooltip() {
this.setState({ showTooltip: true })
}
render() {
return (
<div onClick={this.showTooltip}>
{this.renderTooltip()} { /* function which contains the JSX/HTML to show the toolip */ }
<span className="tag--label">Tags</span>
</div>
)
}
Hiding is done in the ResultItem, by setting the state and then receiving that as props in the ResultTag.
To summarise:
I have many ResultItem components in a list view
Each ResultItem has a ResultTag in, which when clicked, shows a tooltip above the tag/label
When a ResultTag is visible, and another one in a different ResultItem is clicked, hide all the other ResultTags
You could move the state from within each individual ResultItem into the parent, that way it is centralized in one place and you could enforce logic such that only a certain ResultItem will show its tooltip. You would need to manage the state from within the parent and then pass down a function to each ResultItem (and probably down again into its ResultTag) to handle the click.
I wrote a sample app which shows similar behaviour (although slightly different), I wrote it to demonstrate how to add a border to each item in a list. You can see how I stored the state in the parent and how I passed down the means to read and update it to the children via props. You would of course have to change the logic to enforce only a single item being active, currently it supports any item in the list being 'active'. I wrote it for an answer located here: https://stackoverflow.com/a/38646533/1515758

Categories

Resources