React access sub-components properties in main component - reactjs

Would it be possible to access a sub-components properties in the main component in React?
For example I'm trying this: I've got a main component MyComponent and a SubComp sub-component that renders a button. Would it be possible to set the state of MyComponent equal to the tex property of the clicked SubComp?
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'Initial State'
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({name: SubComp.tex});
}
render() {
return (
<div>
<SubComp onClick={this.handleClick} tex="but1"/>
<SubComp onClick={this.handleClick} tex="but2"/>
<h1>{this.state.name}</h1>
</div>
);
}
};
class SubComp extends React.Component {
constructor(props){
super(props);
};
render(){
return(
<button onClick={this.props.onClick}>Click Me</button>
);
}
}
I've tried to do it in the handleClick method with SubComp.tex but it's obviously not working.
Thanks!

Pass the tex prop in SubComp via the callback:
render() {
return (
<button onClick={() => this.props.onClick(this.props.tex)}>Click Me</button>
);
}
And use it in the handleClick of MyComponent:
handleClick(tex) {
this.setState({name: tex});
}

Yes, this is definitely possible. Your idea of passing the function from the main component was right, but to achieve what you are trying to do, you could pass a parameter to the function, like this:
handleClick(e) {
this.setState({name: e.target.value});
}
Notice that I have added the e as a parameter to your handleClick function. This is the click event received from clicking the button. We then set the state equal to the value from this event.

You can also convert SubComp to functional component and pass it handleClick which you defined inside MyComponent as props:
const SubComp = ({handleClick}) => {
return <button onClick={handleClick}>Click me</button>
}
Then pass it handleClick method like so: <SubComp handleClick={this.handleClick} />

Related

Conditional rendering in react prop

I want to ask if this possible in react while passing props or something similar. Eslint underlined the whole process in red.
Component A,
enter code here
<div>
<button style={{style:props.submit}}> Submit</button>
<button style={{style:props.loading}}> Loading</button>
</div>
Component B
import ComponentA from 'A',
export default class ComponentB extends Component {
constructor(props) {
super();
this.state = {
load:false,
}
handleSubmit = (e) => {
e.preventDefault();
this.setState({
load:true,
})
}
render () {
return (
<ComponentA {this.state.load ? (props.loading): (props.submit)}/>
)
}
You can use like that:
const newProps = this.state.load ? {loading: props.loading} : {submit: props.submit}
<ComponentA {...newProps} />

Passing a React click handler to child components

My SquareClicker component renders a SquareGrid, which in turn contains clickable Squares:
class SquareClicker extends React.Component {
constructor(props) {
super(props);
this.state = {
grid: Array.from(Array(5).keys()).map(
i => Array.from(Array(5).keys()).map(
j => <Square key={((i*5)+j).toString()} onClick={this.handleClick}/>
)
)
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
console.log("A square has been clicked.");
}
render() {
return (
<div className="square-clicker">
<SquareGrid grid={this.state.grid}/>
</div>
);
};
}
class Square extends React.Component {
render() {
return (
<div className={"square"} />
);
};
}
When I click on squares, nothing is logged to the console.
This question is similar - but as you can see, I have bound the handleClick function to the component context with this.handleClick = this.handleClick.bind(this);.
How do I make my squares clickable?
I misread your post initially, sorry (I got <Square> and <SquareGrid> mixed up), try this in setting your <Square> component...
j => <Square key={((i*5)+j).toString()} click={this.handleClick}/>
Then in your <Square> component, set render() as so...
render() {
return (
<div
className={"square"}
onClick={(e) => this.props.click(e)}
/>
);
}
You have to pass click event to SquareGrid
// In SquareClicker
<SquareGrid grid={this.state.grid} click={this.handleClick} />
and inside SquareGrid component, you will use click prop like below:
class SquareGrid extends React.Component {
...
return (
// ...you code
<Square click={this.props.click} />
)
}
and then inside Square component pass this prop again
class Square extends React.Component {
render() {
return (
<div className={"square"} onClick={this.props.click}/>
);
};
}

How to access method of the child component from parent in reactjs

I'm trying to call child component from parent component in reactjs using refs.but it throws error saying showModal() is not a function when I tried to call.
//app.js
class app extends Component {
constructor(props) {
super(props);
this.POPUP = React.createRef();
}
showModal(){
this.POPUP.showModal(true);
}
render() {
return (
<React.Fragment>
<span><a onClick={() => this.showModal()}>Show</a></span>
<POPUP onRef={ref => (this.POPUP = ref)}></POPUP>
</React.Fragment >
)
}
}
popup.js
class POPUP extends Component {
showModal(show) {
console.log('showmodal');
}
render() {
console.log(this.props.showModalPopup);
<React.Fragment>
<Modal
position="center">
<div>
//code
</div>
</Modal>
</React.Fragment>
)
}
}
Is there any alternative in nextjs.please help
https://reactjs.org/docs/refs-and-the-dom.html#accessing-refs
First of all if you want to access that POPUP instance you should do
this.POPUP.current.showModal(true);
BTW Your showModal function needs to be bound to the child component if you intend to alter its state.
However, even this is doable - this is usually not the recommended way of doing React.
If you want the parent to decide if showModalPopup should be true, you probably should keep the state inside of your parent component:
class App extends Component {
constructor(props) {
super(props);
this.state = { showModalPopup: false };
this.showModal = this.showModal.bind(this);
}
showModal(){
this.setState({ showModalPopup: true });
}
render() {
return (
<React.Fragment>
<span><a onClick={this.showModal}>Show</a></span>
<POPUP show={this.state.showModalPopup}></POPUP>
</React.Fragment >
)
}
}
const POPUP = ({ show }) => (
<Modal show={show} position="center">
// your content.
</Modal>
)

Reuse a react component with different method calls

I want to create a component with a simple form, lets say with 4 input fields and a button to submit. When the user clicks submit, a POST request will be made.
But then I want to reuse the same component to make a PUT request. How can I achieve that?
Pass a function from a parent component to you child component (the form):
https://codesandbox.io/s/4x3zjwxwkw
const App = () => (
<div>
<CreateRecipe />
<UpdateRecipe />
</div>
);
class CreateRecipe extends React.Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(e) {
e.preventDefault();
console.log("Do POST recipe");
}
render() {
return (
<div>
<MyForm title="POST Recipe" onSubmit={this.onSubmit} />
</div>
);
}
}
class UpdateRecipe extends React.Component {
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
onSubmit(e) {
e.preventDefault();
console.log("Do GET recipe");
}
render() {
return (
<div>
<MyForm title="GET Recipe" onSubmit={this.onSubmit} />
</div>
);
}
}
const MyForm = ({ title, onSubmit }) => {
return (
<div>
<h2>{title}</h2>
<form onSubmit={onSubmit}>
<input type="text" />
<button type="submit">Submit</button>
</form>
</div>
);
};
EDIT: Per the comment, you can absolutely separate the POST and GET submit functions, but this duplicates logic a bit. What could be better is to have the <App /> component own the two submit functions, and pass them respectively to <UpdateRecipe /> and <PostRecipe />, maybe even the titles too! I'll let you compose this however you'd like, but hopefully this shows you the flexibility of React.
You can pass in a method as a prop to the component - that way you can define the functionality outside of the component and let it execute it within the components scope.
An example of this would be passing in a onPress event to a Button, or an onClick event to any other component.
You can pass the method into the component as a prop and then reference props in your submit function like this:
submit = () => {
var data = {
method: this.props.method,
...
};
fetch('/url/', data);
}

Trigger event when the state of child of another component changed in react

Let say I have two components called A and B.
B has a status which keeps changing and I would like to pass the status to A so that I can trigger event when certain condition is met.
How do I keep monitoring/getting state of child from another component in React?
Thanks!
When component on the same level:
class Parent extends React.Component {
constructor() {
super();
this.state = {
status: "B not clicked"
}
this.componentBchangeHandler = this.componentBchangeHandler.bind(this);
}
componentBchangeHandler(value) {
this.setState({ status: value })
}
render() {
return (
<div>
<ComponentA status={this.state.status} />
<ComponentB componentBchangeHandler={this.componentBchangeHandler} />
</div>
)
}
}
const ComponentA = (props) => <div>{props.status}</div>;
const ComponentB = (props) => <div onClick={() => props.componentBchangeHandler("some val")}>click me</div>;
https://codesandbox.io/s/k29mn21pov
And check out the documents I mentioned earlier.
If you're talking about a parent-child relationship, all you'd have to do is define a function that changes state on A and pass it as prop to B, like so:
class A extends Component {
constructor(props) {
super(props);
this.state = {
changed: false,
}
}
_statusChange = () => this.setState({ changed: !this.state.changed });
render() {
return(
<div>
<span>State on A: { this.state.changed.toString() }</span>
<B changeHandler={this._statusChange} />
</div>
)
}
}
class B extends Component {
render() {
return(
<div>
<button onClick={this.props.changeHandler}>Click me</button>
</div>
)
}
}
const App = () => (
<A />
);
If they should be on the same level, by convention, you should define a third component, wrap A and B in it, again passing state as props between them.

Resources