I made a dummy React component that does nothing but prints out its this value.
import React from 'react'
import ReactDOM from 'react-dom'
class MyComponent extends React.Component {
constructor() {
super()
}
componentDidMount() {
console.log(this)
}
render() {
return <div />
}
}
const myComponent = new MyComponent()
console.log(myComponent)
ReactDOM.render(<MyComponent />, document.getElementById('app'))
I expected that console.log(myComponent) would produce the same result as console.log(this). However, the latter has additional properties (e.g. _reactInternalFiber) and some properties are different (e.g. context, props).
My question is, how is React or ReactDOM able to provide these additional attributes? You would think that all instances of MyComponent would have the same attributes since they have the same constructor() function, but that is not the case here.
Related
I'm trying to understand how the context API works. I'd like to keep a global state that I can update from any Class Component. Currently, when I try to update my Context using the provided function, It only updates the value locally. In my code, I try to update a field "Day" into "Hello", and the change can be seen only when Writer is rendered. As soon as I ask my browser to render "Reader", the value is "Day" again. Why does this happen? Here's my code, I simplified it as much as I could:
index.js:
import React from "react";
import ReactDOM from "react-dom";
import {ThemeContextProvider} from "./ThemeContext";
import App from "./App";
ReactDOM.render(
<ThemeContextProvider>
<App />
</ThemeContextProvider>,
document.getElementById("root")
);
app.js:
import React from "react";
import Writer from "./Writer.js";
import Reader from "./Reader.js";
import { Context } from "./ThemeContext.js";
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
class App extends React.Component {
static contextType = Context;
constructor(props) {
super(props);
}
render() {
return (
<div className="app">
<Router>
<Switch>
<Route path="/writer" component={Writer}></Route>
<Route path="/reader" component={Reader}></Route>
</Switch>
</Router>
</div>
);
}
}
export default App;
context.js:
import React, { Component } from "react";
const Context = React.createContext();
const { Provider, Consumer } = Context
// Note: You could also use hooks to provide state and convert this into a functional component.
class ThemeContextProvider extends Component {
state = {
theme: "Day"
};
setTheme = (newTheme) => {
this.setState({theme: newTheme})
};
render() {
return <Provider value={{theme: this.state.theme, setTheme: this.setTheme}}>{this.props.children}</Provider>;
}
}
export { ThemeContextProvider, Consumer as ThemeContextConsumer, Context };
writer.js:
import React from "react";
import {Context} from "./ThemeContext";
class Writer extends React.Component {
static contextType = Context
constructor(props) {
super(props);
this.write = this.write.bind(this)
}
write () {
this.context.setTheme("hello")
}
render() {
return (
<div>
<button onClick={this.write}>press</button>
<p>{this.context.theme}</p>
</div>
);
}
}
export default Writer;
reader.js:
import React from "react";
import { Context, ThemeContextConsumer } from "./ThemeContext";
class Reader extends React.Component {
static contextType = Context;
constructor(props) {
super(props);
}
render () {
return(
<div>
<p>{this.context.theme}</p>
</div>
);}
}
export default Reader;
how do you handle the maneuver to different pages? If right now, you handle it manually by typing it directly in the search top browser input placeholder. Then it will not work since the page getting refresh. Using just context api will not make your data persistant. You need to incorporate the use of some kind of storage to make it persistant.
Anyhow, your code should work if there's not page refresh happen. To see it in different pages tho, you can and a Link (from react-router-dom package) or basically a button to redirect you to different pages, like so:-
just add this in your Writer.js component for testing purposes:-
import React from "react";
import { Link } from 'react-router-dom'
import {Context} from "./ThemeContext";
class Writer extends React.Component {
static contextType = Context
constructor(props) {
super(props);
this.write = this.write.bind(this)
}
write () {
this.context.setTheme("hello")
}
render() {
return (
<div>
<button onClick={this.write}>press</button>
<p>{this.context.theme}</p>
<Link to="/reader">Go to Reader page</Link>
</div>
);
}
}
export default Writer;
I have a question about ReactJS and components, specifically about how functions interact within the component system.
In this example:
// Index.js
import React from ‘/reactʼ;
import ReactDOM from ‘/react-domʼ;
import App from ‘./App.jsʼ;
ReactDOM.render(<App />, document.getElementById(‘rootʼ));
// App.js
import React from ‘/reactʼ;
class App extends React.Component {
constructor(props) {
super(props);
this.state = {someProp = ‘ʼ};
};
functionA = (e) => { console.log(e);
};
Render() {
return <div><ComponentA /></div>
};
};
export default App;
// ComponentA.js
import React from ‘/reactʼ;
import App from ‘./../App.jsʼ;
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.state = {someProp = ‘ʼ};
};
functionB = App.functionA
Render() {
return(
<div>
<input onSubmit={this.functionB} />
</div>
);
};
};
export default ComponentA;
ComponentA imports App.js and attempts to assign App.functionA to functionB and then call it in the JSX. This results in a failure basically saying that the function is not defined.
I know this is NOT the way to function share (I have learned about passing functions through props etc).
I simply just want to know WHY this does not work, to help me better understand the mechanics of React, and Javascript in general.
Thank you,
Curtis
To call a function from another React component, you can write static methods in ES6 notation. If you are using ES7, then you can also write static properties.
You can write statics inside ES6+ classes this way:
class Component extends React.Component {
static propTypes = {
...
}
static someMethod(){
}
}
Working Demo about static function
My noob brain finally figured it out lol... I think.
Basically because an instance of the class [the App component] was not initialized within the scope of ComponentA, the App function is not accessible.
This made it work (DISCLAIMER: I DO NOT PLAN ON DOING THIS, I KNOW ITS TERRIBLE CODE)
// ComponentA.js
import React from ‘/reactʼ;
import App from ‘./../App.jsʼ;
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.state = {someProp = ‘ʼ};
this.appInstance = new App();
}
functionB = (e) => {
this.appInstance.functionA(e);
}
Render() {
return(
<div>
<input onSubmit={this.functionB} />
</div>
);
}
};
export default ComponentA;
I'm trying to use componentDidMount to set data from axios to component state but it doesn't work
I checked it by this simple code
import React, { Component } from "react";
import ReactDOM from "react-dom";
import axios from 'axios';
import "./styles.css";
class App extends Component {
constructor(props){
super(props);
state:{
textures:null
}
componentDidMount(){
let data = axios.get('http://127.0.0.0:8000/wall)
.then(res => {
this.setState({textures:res}
});
)
}
render() {
return (this.state.textures);
}
}
export default new App();
in index.js
import App from '/app.js';
console.log(App.render());
the output is null
Move your state object to the class property from the constructor.
Your constructor has its local state variable which has nothing to do with component state.
You have to either set the property from the constructor or intialize from the class.
class App extends Component {
state = {
textures: null
}
............
import React, { Component } from 'react';
class one extends React.Component
{
constructor()
{
super();
this.state = {
number:26
}
}
render()
{
return(
<div></div>
);
}
}
export default one;
import React, { Component } from 'react';
import one from './one'
class HomePage extends React.Component
{
render()
{
return(
<div>{one.state.number}</div>
);
}
}
export default HomePage;
is it possible to access number state
is there any way to access state of one component into another component?
please suggest me if any solution is present.
As Shubam has explained it, Though I would like to form it as a complete answer
First of all, I would like to let you know that Never Use lowercase letters to name your React Components.So name your component to One instead of one.
Now Comming back to your question:-
No This is not Possible, If your app contains few components then it's better to pass the state object as the props, But if your app contains too many components then better to use predictable state containers like Redux or Flux rather than passing state as props.
So you may apply these changes and I hope You will get What You Desire:-
One Component:-
import React, { Component } from 'react';
import Homepage from './homepage';
class One extends React.Component
{
constructor()
{
super();
this.state = {
number:26
}
}
render()
{
return(
<Homepage data={this.state}/>
);
}
}
export default One;
Homepage Component:-
import React, { Component } from 'react';
class Homepage extends React.Component
{
render()
{
console.log("this is homepage",this.props);
return(
<div>{this.props.data.number}</div>
);
}
}
export default Homepage;
Please Raise Your doubts if any, Or if you find any error in it.
I'd like to listen to location change using history.listen in one of deep nested child component.
Should the top parent component which has this.props.history pass down the props all the way down to the child components?
I'm using 2.8.1 react-router
I am willing to upgrade to newer version if it allows me to do this easily.
import { withRouter } from 'react-router-dom';
class MyComponent extends React.Component {
render() {
// props also has match, location
const { history } = this.props;
...
}
}
export default withRouter(MyComponent);
You could get history by getting router context.
import React, {PropTypes} from 'react';
class myComponent extends React.Component {
render() {
console.log(this.context.history);
}
}
myComponent.contextTypes = {
history: PropTypes.object
}
export default myComponent;