Can I modify a parent state of a component in ReactJs? - javascript

Let's say I'm having the following component:
class LeftPanel extends React.Component {
constructor(props) {
super(props);
this.state = {abc: 'xyz'};
}
render() {
return (
<div>
<Thumb src={img1}/>
<Thumb src={img2}/>
</div>);
}
Inside the component, there's an inner component called Thumb that goes like there:
class Thumb extends React.Component {
constructor(props) {
super(props);
this.state = { src: props.src };
}
render() {
return (
<div>
<img src={this.state.src}></img>
</div>
);
}
}
Question: Can I modify the state of LeftPanel Component inside Thumb? If yes, how?

create a method in Left panel to handle the event. Then pass the method to the child component.
Now if you want to pass data to the parent I would recommend a library like flux or redux. since redux has a global state it is accessible to all components. When you modify the global state to whole application is rerendered with the new state. The new state is visible by all components.
class LeftPanel extends React.Component {
constructor(props) {
super(props);
this.modifyLeftpanel = this.modifyLeftpanel.bind(this);
this.state = {abc: 'xyz'};
}
modifyLeftpanel(newvar){
//Do something with newvar
}
render() {
return (
<div>
<Thumb src={img1} modifyLeftPanel={this.modifyLeftpanel} />
<Thumb src={img2} modifyLeftPanel={this.modifyLeftpanel} />
</div>);
}
here is the thumb
class Thumb extends React.Component {
constructor(props) {
super(props);
this.state = { src: props.src };
this.doSomething = this.doSomething.bind(this);
}
doSomething(){
this.props.modifyLeftpanel(10);
}
render() {
return (
<div>
<img src={this.state.src}></img>
<button onClick={this.doSomething}>Modify Parent</button>
</div>
);
}

Related

how to pass state values as props to child component

I am trying to pass some constant values which is stored in state of parent component to child component and would like to pass down in tree.
is it right to store the constant values in state of App.tsx or any other suggestion
how can i access for example GrTag or sTag from App.tsx to Subchild component.
App.tsx
class App extends Component {
constructor(props) {
super(props);
this.state = {
sTag : "00D",
pTag : "010",
adTag : "020",
dbTag : "030",
GrTag : "040",
serTag : "00E",
modTag : "060",
iTag: "018"
};
}
render() {
return(
<div >
<Child {...this.state}/> //is this right way to pass
</div>
);
}
}
Child.tsx
class Child extends Component {
constructor(props) {
super(props);
}
render(){
return(
<div>
{
<Subchild /> //want to pass the state values from App.tsx
}
</div>
);
};
}
Subchild.tsx
class Subchild extends Component {
constructor(props) {
super(props);
}
render(){
return(
<div>
{
// want to print sTag value here
}
</div>
);
};
}
The way you are spreading the state {...this.state} will pass all the state values as props to the child components . If you need all the state values in your Child component as props then what you are doing is fine .
But if you just need the stag from the App inside the subChild then you can do
<Child {...this.state}/>
In your Child.tsx
<Subchild {...this.props} />
To solve your problem, pass the props from the child to the sub child. Like this;
class Child extends Component {
constructor(props) {
super(props);
}
render(){
return(
<div>
{
<Subchild {...this.props}/> //want to pass the state values from App.tsx
}
</div>
);
};
}
But mind you. This is not a good way to pass data to components.
If you have data that can be shared amongst many components in your app, consider using REACT REDUX or MOBX. I personally recommmend using Redux.
App.tsx
class App extends Component {
constructor(props) {
super(props);
this.state = {
sTag : "00D",
pTag : "010",
adTag : "020",
dbTag : "030",
GrTag : "040",
serTag : "00E",
modTag : "060",
iTag: "018"
};
}
render() {
return(
const data = this.state;
<div >
<Child dataToClid = {data}/> //is this right way to pass
</div>
);
}
}
Child.tsx
class Child extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.dataToClid
}
}
render(){
const data = this.state;
return(
<div>
{
<Subchild dataToSubClid = {data}/> //want to pass the state values from App.tsx
}
</div>
);
};
}
SubChild.tsx
class Subchild extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.dataToSubClid
}
}
render(){
const {GrTag, sTag} = this.state;
return(
<div>
<p>{GrTag}</p>
<p>{sTag}</p>
</div>
);
};
}
you can do this way or you can use Context API for pass data from parent to child

How to correctly call function from component in another component

I saw a few similar questions, but about parent/child elements, i have that kind of node tree:
IndexPage -> Modals -> ClientDetails(it's modal component)
-> Header
I want to call ClientDetails.openModal inside Header, tried many ways like creating refs for ClientDetails in indexPage and then pass indexPage to header like prop, but it's works strange, i see refs of props.IndexPage, but when trying access refs directly it's underfind
class IndexPage extends React.Component {
constructor(props) {
super(props);
this.modals = React.createRef();
}
render() {
return (
<Layout>
<SEO/>
<Header indexPage={this}/>
<Story/>
<Products/>
<Clients/>
<Reviews/>
<Partners/>
<Footer/>
<Modals ref={this.modals} />
</Layout>
)
}
}
class Modals extends React.Component {
constructor(props) {
super(props);
this.clientDetailsRef = React.createRef();
}
render() {
return (
<>
<ThankYou/>
<ContactDetails ref={this.clientDetailsRef}/>
</>
)
}
}
class Header extends React.Component {
constructor(props) {
super(props);
this.state = { isActive: false, isSticky: false };
this.toggle = this.toggle.bind(this);
this.indexPage = props.indexPage
console.log(this.indexPage)
console.log(this.indexPage.modals)
}
}
I think you can solve your problem using react.js context.
You wanted to control the Modals component in the Header component. So you tried to reference the Modals component toggle function in the Header component to solve the problem.
I think it is a fine solution.
But in my opinion, sharing state in peer components is also another solution.
So you can use react.js context to share states between two peer components in a parent component of them. I think doing this is following react declarative programming.
Please check this code
Here is a small fiddle for calling a child function from the parent
https://jsfiddle.net/c1qfn9Lx/9/
class Modal extends React.Component {
constructor(props) {
super(props);
this.state= {
showModal: false
}
this.toggleModal = this.toggleModal.bind(this)
}
toggleModal() {this.setState({showModal: !this.state.showModal})}
render() {
const { showModal } = this.state;
return(
<div className="modal">
{showModal &&
<div>
Showing modal
</div>
}
</div>
)
}
}
class TodoApp extends React.Component {
constructor(props) {
super(props)
this.modalRef = React.createRef()
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.modalRef.current.toggleModal();
}
render() {
return (
<div className="parent">
<Modal ref={this.modalRef} />
<button onClick={this.handleClick}>Click</button>
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
I would try doing this:
class IndexPage extends React.Component {
constructor(props) {
super(props);
this.state = {modalsRef: null};
}
render() {
return (
<Layout>
<SEO/>
<Header modalsRef={this.state.modalsRef}/>
<Story/>
<Products/>
<Clients/>
<Reviews/>
<Partners/>
<Footer/>
<Modals ref={r => !this.state.modalsRef && this.setState({modalsRef:r})} />
</Layout>
)
}
}
But please note: the property won't work in the constructor of Header most likely. It should work though by the time you're doing things like Button.onClick callbacks.

How to pass state property to child component in constructor with React.js?

How to pass a state property of the father component as props for the child component in the constructor? I have something like this:
class FatherComponent extends Component {
constructor(props) {
super(props);
this.state = {
status: true
components: [
{ component: (
<ChildComponent
statusAsProps={this.state.status} />
)
}
]
};
}
render(){
return(
<div>{this.state.components[0].component}</div>
)
}
But shows me the error of this.state is undefined.
Is a way to bind "this" of the state as a prop for the children component?
You're using this.state inside itself before it is even defined and assigned a value. That's why the undefined. Avoid complexity and simply render the child component by passing in the required props from the parent's state.
class FatherComponent extends Component {
constructor(props) {
super(props);
this.state = {
status: true
};
}
render() {
return (
<div>
<ChildComponent statusAsProps={this.state.status} />
</div>
)
}
}
It is not a good idea to store components on the state. You can just define that in your render
class FatherComponent extends Component {
constructor(props) {
super(props);
this.state = {
status: true
};
}
render(){
return(
<div>
{ <ChildComponent statusAsProps={this.state.status} }
</div>
)
}
method

How to render an array of components (objects) with specific props in React?

problem in rendering an array of components. this is my pen a link. where you can see the result.
there should be 10 cards in result but it does not render them.
class Main extends React.Component {
constructor(props) {
super(props);
this.state={chng:0}
}
render() {
return (
<div>
<h1>Hello from Main!</h1>
<Card name="sample" />
<CardsHolder />
</div>
)
}
}
class Card extends React.Component {
constructor(props) {
super(props);
}
render() {
return (<div className="card">{this.props.name}</div>);
}
}
class CardsHolder extends React.Component {
constructor(props) {
super(props);
}
render() {
const cards=[];
axios.get('https://randomuser.me/api/?
results=10&inc=name,registered&nat=fr')
.then(json => json.data.results.map(result => (
cards.push(<Card key={result.name.first} name={result.name.first} />)
)))
console.log(cards)
// I think there is correct array of components in Console but it does not render them
return (<ul>{cards}</ul>)
}
}
ReactDOM.render(<Main />, document.getElementById('react-content'))
This will work, Notes to takes:
We do our AJAX requests in componentDidMount method so we can fire a render at the very top mount of our component using setState
While doing that thing, Dont store JSX in your component's state.
your code.

ReactJS calling functions from child component [duplicate]

I have a parent and child compoents and I want to call a parent method in the child component like this:
import Parent from './parent.js';
class Child extends React.Component {
constructor(props) {
super(props);
};
click() {
Parent.someMethod();
}
render() {
<div>Hello Child onClick={this.click}</>
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
};
someMethod() {
console.log('bar');
}
render() {
<div>Hello Parent</>
}
}
This returns an error message:
Uncaught TypeError: _Parent2.default.someMethod is not a function
How can this parent method be called in the child component?
Try this. Passing the function down as props to the child component.
import Parent from './parent.js';
class Child extends React.Component {
constructor(props) {
super(props);
};
click = () => {
this.props.parentMethod();
}
render() {
<div onClick={this.click}>Hello Child</div>
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
};
someMethod() {
console.log('bar');
}
render() {
<Child parentMethod={this.someMethod}>Hello Parent, {this.props.children}</Child>
}
}
You can try doing something like calling the function of parent by passing the state of your parent to the child and then call using the props in child class.
class FlatListItem extends Component{
constructor(props){
super(props)
}
render(){
return(
<TouchableOpacity style={styles.button}
onPress=
{(item)=>this.props.parentFlatlist.delete(item)}></TouchableOpacity>
</Swipeout>
)
}}
And now consider you have a parent class RandomList:
class RandomList extends Component{
static navigationOptions = ({navigation}) =>{
return{
headerTitle: 'Random List'
}
};
state = {
lists : [],
refreshing : false
}
constructor(props){
super(props)
}
delete= (item) =>{
//delete your item
console.log(item)
}
render(){
return(
<BackgroundImageComponent>
<FlatList
keyExtractor={item => item}
data = {this.state.lists}
renderItem = {({item,index}) => (
<FlatListItem onPress={()=>this.seeTheList(item)} item1={item} parentFlatList={this} index={index}>
</FlatListItem>
)}
/>
</ScrollView>
</BackgroundImageComponent>
)
}}export default RandomList
See here, I am passing parentFlatlist={this} and then would be using the same instance later in the child class.
The main idea is to focus upon the way I am able to render the delete function and not to focus upon the code. Forgive me if the code is misplaced or broken.

Categories

Resources