Does React allow getting or setting props outside of components - reactjs

When I have a component inside a component
var MySubComponent;
class MyComponent {
...
getChildProps() {
console.log(MySubComponent.props.nameToGet)
}
...
MySubComponent = withCustomAudio(props => {return(<div>...</div>)});
...
render() {
return(...<MySubComponent {...this.props}/>...)
}
...}
After component render I'd like to get or set the prop of the subcomponent. It returns cant access nameToGet of undefined
Spread attributes is not what I want
(https://zhenyong.github.io/react/docs/transferring-props.html)

No, you won't be able to get/set props like this. It's not the React way. You should read more about thinking in React.
Basically, if you want to change child props in the parent, they should be part of the parent state and passed down to the child as props.
Example:
import React, {Component} from "react";
class Parent extends Component {
state = {
childProp: "Not changed yet"
}
handleChildPropChange = () => {
this.setState({
childProp: "I changed"
})
}
render() {
return <Child myProp={this.state.childProp} onChangeChildProp={this.handleChildPropChange} />;
}
}
class Child extends Component {
render() {
return (
<div onClick={onChangeChildProp}>{this.props.myProp}</div>
)
}
}

Related

Is it possible for me to pass a prop from a child to a parent component on page load?

How can i pass the hello const value which is in the ChildComponent to the App component and store it in the childProps variable of the App component on page load.
import React, { Component } from 'react';
class App extends Component {
render() {
var childProps ''; // I want store the passed const value in this variable;
return (
<div>
<ChildComponent />
</div>
);
}
}
export default App;
class ChildComponent extends Component {
render() {
const hello = 'Hope you are having a good day!';
return <h1>{hello}</h1>;
}
}
export default ChildComponent;
There is no way to pass props from a child component to a parent component. However, we can always pass around functions from the parent to child component. The child component can then make use of these functions.
You can assign a callback to child component from parent component, it will be called once the child is mounted. Store that value in parent class property , if re-render requires maintain a state.
App
class App extends Component {
helloCallback = (str) => {
this.childProps = str
}
render() {
return (
<div>
<ChildComponent helloCallback={helloCallback}/>
</div>
);
}
}
Child
class ChildComponent extends Component {
hello = 'Hope you are having a good day!'
componentDidMount() {
this.props.helloCallback(this.hello)
}
render() {
return <h1>{this.hello}</h1>;
}
}

Call child function in parent with i18next react

I used React.createRef() to call child method, like that
import Child from 'child';
class Parent extends Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
onClick = () => {
this.child.current.getAlert();
};
render() {
return (
<div>
<Child ref={this.child} />
<button onClick={this.onClick}>Click</button>
</div>
);
}
}
Child class like that
export default class Child extends Component {
getAlert() {
alert('getAlert from Child');
}
render() {
return <h1>Hello</h1>;
}
}
It works well. But when I want to use i18next to translate child component, I have to add withTranslation() to use HOC.
import { useTranslation } from 'react-i18next';
class Child extends Component {
getAlert() {
alert('getAlert from Child');
}
render() {
const { t } = this.props;
return <h1>{t('Hello')}</h1>;
}
}
export default withTranslation()(Child);
Then return error: Function components cannot be given refs.
Means cannot use ref in <Child /> tag. Is there any way to call child function after add i18next?
This is a problem since the withTranslation HOC is using a function component. By wrapping your Child component with a HOC you essentially are placing the ref on the withTranslation component (by default).
There are multiple ways to fix this problem, here are the two easiest:
Using withRef: true >= v10.6.0
React-i18n has a built in option to forward the ref to your own component. You can enable this by using the withRef: true option in the HOC definition:
export default withTranslation({ withRef: true })(Child);
Proxy the ref using a named prop
Instead of using <Child ref={this.child} />, choose a different prop to "forward" the ref to the correct component. One problem though, you want the ref to hold the component instance, so you will need to assign the ref manually in the lifecycle methods.
import Child from 'child';
class Parent extends Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
onClick = () => {
this.child.current.getAlert();
};
render() {
return (
<div>
<Child innerRef={this.child} />
<button onClick={this.onClick}>Click</button>
</div>
);
}
}
import { useTranslation } from 'react-i18next';
class Child extends Component {
componentDidMount() {
this.props.innerRef.current = this;
}
componentWillUnmount() {
this.props.innerRef.current = null;
}
getAlert() {
alert('getAlert from Child');
}
render() {
const { t } = this.props;
return <h1>{t('Hello')}</h1>;
}
}
export default withTranslation()(Child);

How to get a componenet instance in React

I want to know if there is possible to get the component instance as I need.
I put my new component as a children in the main state, but is no the same object in both files.
I need to reach children state in my MainComponent. Looking in google for componenet instance doesnt help, maybe I am out of focus and the name of this is different.
Here is my MainComponent:
import React, { Component } from 'react';
import AnotherComponent from './../whatever/AnotherComponent';
class MainComponent extends Component {
constructor(props) {
super(props);
this.state = {
children: [],
};
}
addChild() {
const { children } = this.state;
this.setState({
children: children.push(<AnotherComponent />)
});
}
getChildrenState(component) {
return component.state(); // this doesn't work!
}
render() {
const { children } = this.state;
return (
<div>
{(children.map(i => (<div key={this.getChildrenState(i).id}>{i}</div>))}
</div>
)
}
And This is AnotherComponent
import React, { Component } from 'react';
class AnotherComponent extends Component {
constructor(props) {
super(props);
this.state = {
id: 144,
};
}
render() {
return (
<div>
Here it is my cHild!
</div>
)
}
Putting <AnotherComponent/> to the state doesn't make sense because it's React element object that isn't associated with specific component instance.
Accessing children state in parent component breaks the encapsulation and indicates design problem.
The instance of class component should be retrieved with a ref, and doing so to access instance state is the last resort that may be needed to extend third-party components that don't provide desired functionality.
If AnotherComponent is first-party component, it should be designed accordingly, to not require state to be accessed from the outside:
render() {
return (
<div key={this.state.id}>{this.state.id}</div>
)
}
If the output needs to be more flexible, it can make use of render prop pattern:
render() {
const render = React.Children.only(children);
return (
<div key={this.state.id}>{render(this.state.id)}</div>
)
}
And used like:
<AnotherComponent>{id => <div>{id}</div>}</AnotherComponent>
If you want to access the state of the child component ( here AnotherComponent ) then you can either :
Maintain the state inside the AnotherComponent and pass the value to the parent ( here MainComponent ) on a change listener ( whenever the state changes ), or;
Maintain the state in the parent ( here MainComponent ) and pass the value to the child as prop.
Let me know if you want me to give an example implementation.

How to use Higher Order function (or alternative) for wrapping a React component without the component continually unmounting?

I have a React component (Parent) within which there is another componet (Child) that is wrapped using a Higher Order function (HOWrapper). The problem I am having is that each time the Parent component renders, the Child component unmounts and then re-mounts. I need to find a way that prevents the Child component from unmounting, but still continue to wrap it in a component whose name is dynamically assigned. I also want the option to pass additional parameters to the HOWrapper function, that may also be dynamically generated in the render() function of Parent. Any ideas?
Parent component:
import { HOWrapper } from './somepath';
import Child from './someotherpath';
export default class Parent extends Component {
...
render(){
let ChildWrapper = HOWrapper(Child);
return (
<ChildWrapper {...this.props} />
);
}
}
Higher Order function:
export function HOWrapper(WrappedComponent) {
return class Blanket extends Component {
constructor(props) {
super(props);
this.state = {
...
};
}
...
render() {
return (
<WrappedComponent
{...this.props}
/>
);
}
}
}
Because an HOC returns a component, a more typical approach to using them is once when exporting them, not on every render call.
let YourComponent = props => <div />
export default HOC(YourComponent)
Then if you want to do anything dynamic pass new props to it.
render() { return <YourComponent dynamicProps={foo} /> }

child of the component "this" value and how do I get to parent component?

child of the component "this" value and how do I get to parent component?
ex:
class AComponent extends Component{
static getThis(){
return this;
}
}
class MainComp extends Component{
componentDidMoud(){
console.log(AComponent.getThis());
}
}
in this way, how do I get it?
You shouldn't get the parent component from a child component. If you need to do something (ie affect parent component state), then pass a function from the parent to the child as a prop to do it. If you need to read something, then pass the relevant data from parent to child as a prop to read it.
You can pass props down to children, whether it be a simple primitive value for the child component to use, or a function that can be used by the child component to change the state of the parent component. Here's a simple example.
ParentComponent.js
import React, { Component } from 'react';
import ChildComponent from './ChildComponent';
class ParentComponent extends Component {
constructor(props) {
super(props);
this.state = {
someState: true
};
this.someFunction = this.someFunction.bind(this);
}
someFunction() {
this.setState({
someState: false
});
}
render() {
return (
<ChildComponent aFunc={this.someFunction} aString="someValue"/>
);
}
}
ChildComponent.js
import React, { Component } from 'react';
class ChildComponent extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className={this.props.aString}>
<button onClick={this.props.aFunc}>
Some text
</button>
</div>
);
}
}

Resources