who knows how change props in my component use refs in react js ?
<MyComponent
ref={'input1'}
name={'input1'}
label={interestsName}
disabled={ false}
onChange={this.myFunction}/>
after onChange i call function with
myFunction =()=>{console.log(this.rews[input1].props.disable);}
May I change props use refs without use state? Because I have many '15' components such as this component. Thanks.
You cannot change props from child class, for more please refer to link.
For your functionality use you can use state to change value on the change event. And one more thing you should keep the logic of changing component properties should remain inside a component. This will help us to maintain different states for different components.
class MyComponent extends React.Component {
constructor(props) {
this.state = {
disable: props.disabled
};
}
myFunction() {
console.log(this.state);
}
}
You can iterate over the above component and it can be used for 15 times and different states can be managed for every element
You shouldn't use ref in this case, you should use states to change your child props:
class MainComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
disable: false,
};
this.onChange = this.onChange.bind(this);
}
onChange() {
this.setState({ disable: true });
}
<MyComponent
name="input1"
label={interestsName}
disabled={this.state.disable}
onChange={this.onChange}
/>
}
In <MyComponent> use componentWillReceiveProps() to detect new props value.
Related
I can't figure out how to use multiple states in a single React component, since I can't call useState in a class.
What I need to achieve is to have multiple states and "monitor" them with useEffect independently.
Currently I have something like this, but from what I understand I can't have anything like useEffect based solely on object fields. How should I go about this?
class ShowPosts extends Component {
constructor(props) {
super(props);
this.state = {
posts: [],
sorting:'desc',
lastPostDate:'none',
hasMore:false,
pageNumber:1
};
}
class ShowPosts extends Component {
constructor(props) {
super(props);
this.state = {
posts: [],
sorting:'desc',
lastPostDate:'none',
hasMore:false,
pageNumber:1
};
componentDidUpdate(prevProps, prevState, snapshot){
//write the code to monitor this.state and prevState in here
}
}
ComponentDidUpdate is called after every render. This will be same as useEffect for functional components.
This is my parent code:
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
tags: [],
};
}
componentDidMount() {
this.getTags();
}
getTags() {
//method gets tags from the backend
}
render() {
return <Child tags={this.state.tags} />;
}
}
And this is basically my child component:
export default class Child extends Component {
constructor(props) {
super(props);
this.state = {
tags: props.tags,
};
}
componentWillReceiveProps(nextProps) {
this.setState({
tags: nextProps.tags,
});
}
}
But when I console log tags somewhere in the Child component, it is undefined. Maybe it is undefined because the child component gets rendered before the parent component calls the method getTags? Or is there any other problem with this code? And how can I avoid this problem that tags are undefined in the child component?
Cheers
To avoid your problem, you shouldn't be rendering your Child component until the this.state.tags has any useful values.
Here is how you can do it and also show a "Loading..." text, so the user isn't worried the page is broken.
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
tags: [],
};
}
componentDidMount() {
this.getTags();
}
getTags() {
//method gets tags from the backend
}
render() {
return this.state.tags.length ? (
'Loading...'
) : (
<Child tags={this.state.tags} />
);
}
}
Your child component will definitely get rendered with the empty 'tags' array as a prop. Then, when getTags() returns the data, the newly populated tags array will be passed to the child as a prop, forcing the child to get re-rendered with the new data.
It should be the empty array though, not "undefined". You might check your getTags() method and the API you are calling to make sure you aren't getting "undefined" from there.
componentWillReceiveProps is legacy and should not be used. See the following link in the React docs for details: https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops
That documentation will walk you through what to do if you need to perform side effects as a result of changing props.
Right now the only thing is componentWillReceiveProps is to set local state to the props, which is totally superfluous. Is there something else you are needing to do there?
I know that their are some similar questions like this, however im still confused on the following.
When to use state like this
Class Example extends Component {
state = {
name: ''
}
}
Over constructor props
Class Example extends Component{
constructor(props) {
super(props);
this.state = {
name: ''
}
}
}
Does it have something to do with method binding ? because i can use onChange fine without binding it like this:
this.onChange = this.onChange.bind(this)
I can still call onChange like
onChange = (e) => {
}
<Component onChange = {this.onChange} />
The difference in your examples is purely syntactical, not functional. You can use both of them with the same effect.
Generally you assign a state in the constructor function when you want to compute the state based on some runtime logic (eg. based on the passed props). In that case you'll write it like that:
class Example extends Component {
constructor(props) {
this.state = {
fullName: props.firstName + ' ' + props.lastName
}
}
}
in react new version you can initialise state directly without using this
constructor(Props){
super(props)
this.state ={
}
}
both of them are correct. you can use any of them.
i will choose first one because it is less code
and for any method you can directly use them like
onChange = (e) => {
}
<Component onChange = {this.onChange} />
there is no need to bind method in new versions of react
I have the following structure:
class Parent extends React.Component {
componentDidMount() {
document.addEventListener('keydown', () => {
this.value++;
})
}
this.value = 0;
render() {
return (<ChildComponent value={this.value} />)
ChildComponent simply renders the value:
class ChildComponent extends Component {
render() {
return (
<div>
{this.props.value}
</div>
);
}}
I don't want to rerender Parent component on every KeyDown event, that's why I don't put a value to the state.
I want ChildComponent rerenders on every KeyDown event, but ChildComponent renders only once because it doesn't get changed value and always shows 0 although this.value is changing.
Is it possible to rerender ChildComponent while changing this.value of the ParentComponent or I should place logic into ChildComponent using setState to render correct result?
You should add the value to parent state. This is simply the way React works. Even if you could manually trigger a rerender on the child component, it would still be 0 as still 0 is provided props. When React detects state has changed on Parent component, it will calculate the virtual dom of all child elements, do a diff on the virtual dom vs the real dom, then selectively update the real dom with those values (only the inner text of the Child component div will actually be new). React is incredibly optimised to handle rerendering using the virtual dom, and you should not worry about performance loss of this situation.
The reason the child component didn’t get called when value changes because you are overriding normal variable value but not react component state. So inorder to call child component when value changes you need to manage value property in component state of parent so whenever you modify it’s value using setState, component will re render
Change
class Parent extends React.Component {
componentDidMount() {
document.addEventListener('keydown', () => {
this.value++;
})
}
this.value = 0;
render() {
return (<ChildComponent value={this.value} />)
}
}
To
class Parent extends React.Component {
constructor(props){
super(props);
this.state = {
value: 0
}
}
componentDidMount() {
document.addEventListener('keydown', () => {
this.setState({value: this.state.value++});
})
}
render() {
return (<ChildComponent value={this.state.value} />)
}
}
class RaisablePaper extends Component {
constructor(props) {
super();
this.state = {
state1: "state1",
openNow: props.boxOpen,
};
}
}
I am trying to send value to this class by doing <RaisablePaper boxOpen={this.state.dOpen}/>. But whenever the dOpen gets changed it does not seem to update the openNow. Help would very much appreciated.
You are setting the state before mounting the component in the constructor, which will not be fired again when the props change. For that you can use React's componentWillReceiveProps, which will be called when new props are sent to the component.
class RaisablePaper extends Component {
constructor(props) {
super();
this.state = {
state1: "state1",
openNow: props.boxOpen
};
}
componentWillReceiveProps(props) {
this.setState({
openNow: props.boxOpen
});
}
}
It would be simpler to use the props directly instead of worrying about syncing it to your state. It's a good idea in general to rely on props as much as possible, and only involve state when absolutely necessary.
But Fabian Schultz is absolutely right -- your constructor only runs once, before the component is mounted, so you'll never receive the subsequent updates if the component is relying on state which is initialized during construction.
I'm just imagining how you're using the boxOpen state to show an example; you can follow the same general idea with whatever your render method is doing.
class RaisablePaper extends Component {
render() {
return (
<div className={this.props.boxOpen ? 'is-open' : ''}>
Here's some content...
</div>
);
}
}