How to solve the problem attached in the drawing?
I am talking about the best possible way of getting used without using redux.
When a button is pressed in a nested component, something has to change in another (it does not inherit from itself)
For example, in one component I choose the element and in the other I want to display details.
You can have a shared parent hold the state you want to change and pass to the first component while sending the onClick function to the other. Then, when one component changes the state through the onClick function, the changed prop will be passed on to the second component.
You should not change the state from one component via another component:
https://reactjs.org/docs/faq-state.html
props get passed to the component (similar to function parameters)
whereas state is managed within the component (similar to variables
declared within a function).
For "States" between components, you should use props from the store, via react-redux
First of all, I will suggest you to look into lift state up in react.
Now, how you'll do it: (just a pseudo example)
ParentComponent
onClick={this.onClick} stateProps={this.state.stateProps}
onClick() {
this.setState()
}
ComponentA
onClick={props.onClick}
ComponentB
console.log(props.stateProps)
The component will be used like: (again just a pseudo example)
<ParentComponent onClick={this.onClick} stateProps={this.state.stateProps}>
<ComponentA onClick={props.onClick} />
<ComponentB stateProps={props.stateProps} />
</ParentComponent>
Related
return
<div>
<RadioOptions />
<GenButton />
<OutputPass />
</div>
I recently worked on my side-project and I found an issue in my code. inRadiooptions I used some useState hooks, and I want to pass that state from Radiooptions component to its parent(passGen) and then from there, pass that state toGet Button component to check some condition and if nothings wrong, generate the password. (I'll also attach my GitHub repo for better access to my source code)
https://github.com/arviinmo/palora/tree/main/components/passwordgenerator
You can't pass props from child to parent in React, it's only one way (from parent to child).
You should either:
Put the state in the parent component and manipulate it from the child component by passing the setter function in the props
Use something like Redux Toolkit to create a global state that all components can have access to
I am not experienced enough React delevoper yet, so i am having issue with rendering 2 separate components, which are comunicate with each other. So the main task is simple:
user click the button create user form
adding 1 component combination
Btw i want to provide to user the possibility to create as much component combination as he will want. What pattern should i look for? I don't understand how to create two communicating components inside different parent containers.
Here is gif for better understanding
If Main is a component and Sidebar is a component you want to store state in Main and pass props to Sidebar.
Make Main a stateful class based component with a constructor function and store something like this:
this.state = {
addInput: false
}
Then in Main write a click handler. When the user clicks a button set addInput to true.
function addComponent() => {
this.setState({
addInput: !this.state.addInput
})
}
Add an onClick event handler to the button like this:
<input type="button" onClick={this.addComponent()} />
Then inside Main pass props to Sidebar:
<SideBar addInput={this.state.addInput} />
Then inside Sidebar you can use props and a ternary to decide whether or not to display the input section based on whether addInput is true or false.
I wrote this quick and it's a basic rundown. Check out the React props docs for more information.
Instead of using a boolean inside Main's state you could also use a number and dictate how many input boxes show up in Sidebar based on the number value.
Here is an example that I wrote showing another person how to pass props in a React component. Check it out and you'll see an example of passing props to a child component. Look at Parent and Child components and see how props are passed and also state being updated by an onClick event.
Class "App" receives two props - isClicked(bool) & onClick(func)
My intention is to toggle between red/blue text when a div area is clicked.
But this logic is called from another class, called "Call". Call will pass the initial boolean prop (isClicked) and the onClick function down to App.
I don't understand how this onClick() function that is defined in the Call class can modify the App.props.isClicked variable.
What is the best way to approach this problem?
Here is my code in action:
https://codesandbox.io/s/03m408930w
Since Call was the parent component for App all you need to do is add isClicked as a prop when we call the component. And we store the value of isClicked in the state of our component. So everytime it's clicked our state changes which rerenders app.
I edited your code and here it is
https://codesandbox.io/s/31pl8zp7n1
Lets say I have the following code:
<View>
<ComponentA>
<TouchableHighLight onPress={this.refs.componentB.foo.bind(this)}><Text>Hey</Text></TouchableHighLight>
</ComponentA>
<ComponentB ref='componentB'>
....
</ComponentB>
</View>
-
class ComponentB extends React.Component = {
foo() {
// do something
}
}
The ref for componentB will be undefined when I try to use it in ComponentA. Im guessing it's because i ComponentA tries to use it before the ref is assigned.
Whats the best way to fix this?
I could have all the functions in the parent component, but it will end up being a huge file if I dont separate it filled with functions that IMO should be contained in the child components.
You could wrap the onPress-handler in a function:
<TouchableHighLight onPress={() => this.refs.componentB.foo()}>
You cannot access any method in <Component B> from <Component A>. This is by design, done on purpose, and for your own good :)
Best to stick to react design principles, and not try to make a shortcut. You will definitely regret any shortcuts later on.
And BTW: A ref is a reference to the mounted component in the DOM, not to the react component. So I don't think you could get it to work anyway. Besides, I would always advise anybody not to use refs, ever (I learned that from a Netflix talk on react).
One way to fix:
Put a doFooInB boolean in state inside your parent <View> component
Pass this doFooInB to <Component B> as a prop.
<Component B> reads the prop, and responds accordingly (with an internal function called from B's render)
Define an onPress event inside parent <View> component and pass function as prop to component A.
onPress simply needs to setState({ doFooInB : true }) or something to trigger re-render, which will trigger the method in component B.
Yes, this is more code, but it really is better than creating some shortcut.
I don't see a problem in having these shared functions in a parent component, using props to call them when something happens in one of the children.
That's actually an encouraged React pattern, because you make your children components easier to test.
If you make ChildA aware of ChildB, you are coupling them instead of having the parent to just coordinate them.
See also this:
https://facebook.github.io/react/docs/more-about-refs.html#cautions
If you have not programmed several apps with React, your first inclination is usually going to be to try to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to "own" that state is at a higher level in the hierarchy. Placing the state there often eliminates any desire to use refs to "make things happen" – instead, the data flow will usually accomplish your goal.
It's not better idea to give ref to component since ref can be done on DOM objects. so, the better solution is to make function in parent component and pass that function as props to child component in onPress() handler of child component call that method as this.props.method which will automatically call the parent component method. In this way parent component method can be executed successfully.
<ComponentA>
constructor(){
this.method = this.methodA().bind(this);
}
methodA(){
}
<ComponentA method=this.methodA/>
<ComponentB>
<TouchableHighlight onPress={()=>{this.props.method}}>
</ComponentB>
I'm trying to make a custom checkbox component (a three-state, actually, but that's irrelevant except to say that I'm not just using an INPUT), and I'm not sure how I can make it able to change "checkedness" from clicks on itself and from a value-set coming down from the parent.
Currently, I have it working as a self-sufficient component that takes an onChange prop with the handler callback that it calls to send the value the parent component after clicks. It uses a state to store the checkedness, which is referenced by the display.
If it were merely a display of checkedness, with value being managed from outside, I'd use props, naturally. If it were only a self-sufficient checkbox component that took an initial value then only responded to clicks, I'd use state, like I am, but my problem is that I want it to be clickable to turn itself on and off, and allow the parent to turn it on and off as well.
I'm a beginner to React and the "React way of thinking" so I suspect I'm just approaching this wrong. I kind of get the impression that the proper way to do this would be for it to be a display-only component that passed clicks up to the parent to deal with, and in turn received props updates for value changes down from the parent, but that would make the component far less reusable, to my mind.
So how would I go about making a checkbox change from both internal and parent sources?
Relevant links are welcome, as well.
You may treat the checkbox as a dumb component, which means that it doesn't hold any internal states, but only receives data from outside via props and then render them. You can see the detailed definition of dumb components here.
Meanwhile, when the checkbox is clicked, such event will be handled by the component's parent, or event ancestors, this is called inverse data flow, which is described in Facebook's Thinking in React blog post.
Moreover, to decide which component should hold certain states, I find the following guidelines very useful:
Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. This is often the most challenging part for newcomers to understand, so follow these steps to figure it out:
For each piece of state in your application:
Identify every component that renders something based on that state.
Find a common owner component (a single component above all the components that need the state in the hierarchy).
Either the common owner or another component higher up in the hierarchy should own the state.
If you can't find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component.
The pseudo-code snippet:
const Checkbox = React.createClass({
// Propagate the event to parents
onClick(evt) {
if (this.props.handleClick) {
this.props.handleClick({checked: evt.target.value});
}
},
render() {
return (
this.props.checked ?
<Input onClick={this.onClick} type="checkbox" label="Checkbox" checked></Input> :
<Input onClick={this.onClick} type="checkbox" label="Checkbox"></Input>
);
}
});
const Container = React.createClass({
handleClick(evt) {
// Change the container's state, which eventually changes the checkbox's view via props.
this.setState({checked: evt.checked});
},
render() {
return (
<div><Checkbox checked={this.state.checked} handleClick={this.handleClick}></Checkbox></div>
);
}
});
You change it from only the parent.
class ParentComponent extends React.Component{
handleChildCheck(){
this.setState({
childChecked: !this.state.childChecked
})
}
render(){
return(
<ChildComponent checked={this.state.childChecked} handleCheck={this.handleChildCheck.bind(this)} />
)
}
}
Now if you wish to control the checked state from the <ChildComponent/> just call this.props.handleCheck() from the <ChildComponent/>
This way the controls will always be available within the <ChildComponent/> via this.props.handleCheck() within the <ParentComponent/> via this.handleChildCheck().