I'm trying to render a new instance of an object but I'm not sure how to call the render function or how to set the state from outside the object itself.
//App.js
import React from 'react';
import './App.css';
import DrawMessage from './components/DrawMessage'
function App() {
var Draw = new DrawMessage();
Draw.setState({
test: 'THIS IS A NEW TEST!'
});
return (
<div className="App">
<header className="App-header">
<DrawMessage/>
<Draw/>
</header>
</div>
);
}
export default App;
//DrawMessage.js
import React from 'react'
class DrawMessage extends React.Component {
constructor (props){
super(props)
this.state = {
test: 'THIS IS A TEST!'
}
}
render () {
return <div className='message-box'>
Hello {this.state.test}
</div>
}
}
export default DrawMessage
using the DrawMessage in the return yields "Hello THIS IS A TEST!" which is the default response
But if I was able to render the Draw i was expecting to see "Hello THIS IS A NEW TEST!" as i want to change the state of "test"
I am assuming that I cant call the render function from Draw the way i did and I don't think I am properly changing the state of test.
Calling setState on a child from a parent is not conventional React. I'd remove all of the following, and instead just invoke DrawMessage in the return of App:
var Draw = new DrawMessage();
Draw.setState({
test: 'THIS IS A NEW TEST!'
});
One way to achieve your goal would be to set the state of DrawMessage in its constructor function, and then change it via componentDidUpdate() when the props passed from App change. If you're considering that route, ask yourself the following: does DrawMessage need to have its own state? If its state is often changed from the parent, it may be better served as part of props. React will re-render DrawMessage when props change.
componentDidUpdate() docs
Via JSX: var myTinyObject = <TinyObject prop1={prop1} prop2={prop2} />;
Via React.createElement: var myTinyObject = React.createElement(TinyObject, { prop1, prop2 }, null);
Related
My Loading component:
import React from 'react'
export default class Loading extends React.Component {
constructor(props) {
super(props)
this.state = {
display: 'none'
}
}
render() {
return (
<div className="loading" style={{display: this.state.display}}>
<span></span>
</div>
)
}
}
And I want change display from App.js
Loading.setState ...
Or
var lng = new Loading()
lng.setState ...
Both of them not work
I want can change state from another class or function
If you want to change display from App.js:
Pass it as prop to Loading component, and keep the state at App.js.
pass some prop from App.js and when it changes - change the state
of display in App.js
Use some global state/store manager like Redux or built-in useContext react-hook, in this case you will be able to change from any component connected to store
Solution sample
A simple solution can be found in a code sandbox example.
Lets say I have a component defined like this -
// actioncomponent.js
import React from 'react';
class ActionComponent extends React.Component {
state = {
isAction: false;
}
doAction = () => {
this.setState({isAction: true})
}
render () {
return (
<div>
Some render stuff..
</div>
)
}
}
export default ActionComponent
From another completely different file I want to set the state for the first component without rendering it in the new file so I need not use refs or props.
// newfile.js
import ActionComponent from './actioncomponent.js'
ActionComponent.doAction()
I'm aware the doAction can't be exported and calling it static doesn't have access to state either. How do I achieve something like this?
In React ecosystem you probably don't need this.
You can pass this method to a child component:
class ActionComponent extends React.Component {
state = {
isAction: false
}
doAction = () => {
this.setState({isAction: true})
}
render () {
return (
<div>
<Child doAction={this.doAction} />
</div>
)
}
}
And then in a Child component you can fire this action
// ...
render() {
<button onClick={() => props.doAction()}>Test</button>
}
If you need to fire action on parent, instead of child you might want to structure your state on upper level, or lift state up.
You can also achieve similar goal without drilling props, but you'll need some state management tool, e.g. Redux or in some cases Context API would be a great fit.
New to React, in the following code I am passing data between two components via the parent. Flow is from Search to the parent App then to another child Sidebar. I am able to send to both from Search to App and App to Sidebar individually but for some reason setState is not behaving as expected making the link to trigger a refresh of <Search updateMenu={this.handleSearchResult} /> as you can see in the console.log code comments below:
import React, { Component } from 'react';
import './App.css';
import Search from './Search';
import Sidebar from './Sidebar';
class App extends Component {
constructor() {
super()
this.state = {
menu: []
}
}
handleSearchResult = (array) => {
// always the correct value
console.log('in ', array);
this.setState( {menu: menuList})
// 1st call : empty
// 2nd call : previous value not showing on 1st call + new value as expected
// does not trigger <Sidebar list={this.state.menu}/>
console.log('out', this.state.menu);
}
render() {
return (
<div className="App">
// not refreshing
<Search updateMenu={this.handleSearchResult} />
<Sidebar list={this.state.menu}/>
</div>
);
}
}
export default App;
Logging this.setState(). Is not so straight forward. this.setState() is asynchronus.
Here is a reference on Medium.
Here is a component:
export default class MyComponent extends React.Component {
componentWillReceiveProps(newProps) {
console.log('RECEIVED PROPS');
}
render() {
return <div>{this.props.foo}</div>
}
}
Here is a wrapper/higher-order-component:
const withSomething = (ComponentToWrap) => {
render() {
return <ComponentToWrap {...this.props} />
}
}
Here is a functional component that wraps MyComponent in withSomething:
export default function WrappedComponent(props) {
const Component = withSomething(MyComponent);
return <Component ... some props ... />
}
Result: props-related lifecycle functions (such as componentWillReceiveProps) in MyComponent never fire, even when I update the props.
What is up with this? Do props-based lifecycle methods not work on wrapped components?
The problem is that since the line that creates the wrapped component is contained in the functional component, it basically creates a new component every time the functional component renders.
This line ends up being included in WrappedComponent's render method:
const Component = withSomething(MyComponent);
...which means Component gets overwritten at every render.
Another clue is to put a componentDidMount() into MyComponent -- it'll fire every time the props update.
Solution is to create the wrapped component somewhere OUTSIDE the functional component, or outside the render method if you are using a regular class component.
Can I use an instance of a reactJS component to render a component.
Eg, Let's say my reactJS component is
class myComponent extends Component{
constructor(props){
super(props)
this.state = {
next:false
}
this.alertSomething = this.alertSomething.bind(this);
this.showNext = this.showNext.bind(this);
}
showNext(){
console.log('wow');
console.log(this.state, this, this.state.next);
this.setState({next:true});
}
alertSomething(){
alert('Alert Something')
console.log(this.state, this, this.state.next);
this.setState({next:true});
}
render(){
return(
<div className='column'>
</div>
)
}
}
export default myComponent
Now, inside my another component can I do;
let x = new displayContent.renderComponent();
render(
<x />
//or
<x.render />
)
// I tried both it didn't work, I thought there mush be some other way to achieve this, after all every component is just a javascript object.
Also at the same time, can I call function to make change in its state. Like.
x.someFunction();
where someFunctino is inside that react component, doing setState.
Is it possible? OR am I missing something?
Edit: I clearly understand that when you want to render a react component, you can always do, <component />.
This question is just out of curiosity, can this be done? if not, then why?, I mean how is that different from other javascript objects.
Well, you can use the React.createElement method to render a component:
React.createElement(Component, params)
but with JSX, this is the same:
<Component />
Refer to Multiple components in the React documentation.
This is not how you're supposed to use React. You don't have to handle object instantiations ; React do this for you. Use composition instead.
render() {
return (
<myComponent />
)
}
Also, if you want to set the state of a child component from a parent component, you should probably move the logic in the parent.
Probably you are looking for something like this.
import React, { Component } from "react";
import CamCapture from './CamCapture.js';
export default class ProctorVideoFeed extends Component{
constructor(props) {
super(props);
this.Camera = React.createElement(CamCapture);
}
//this.handleVideoClick = this.handleVideoClick.bind(this);
render(){
return(
<div>
<span>{this.Camera}</span>
<button onClick = {this.Camera.StopRecording}>Stop</button>
</div>
)
}
}
Here StopRecording is a function defined inside CamCapture class.