I have two components App and SomeComponent.
I want to get access variable in App from SomeComponent.
App:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
var places = [];
class App extends Component {
state = {isLoading:true}
render(){
bla-bla...}
}
export default App;
SomeComponent:
import React from 'react'
import App from '../App'
class SomeComponent extends React.Component {
componentDidMoint(){
console.log('Check access places array',App.places)
}
render(){
bla-bla...
}
}
export { SomeComponent }
But its coughed out places is Undefined, instead of show empty array. Whats wrong here ?
Yes, I've tried different variants... but no success.
Thanks!
The way to pass data from a parent component to a child component in React is through props. You can e.g. pass the array as the places prop to your Child component and access it from this.props.
Example
class App extends React.Component {
state = { isLoading: true, places: ['foo', 'bar'] }
render() {
return <Child places={this.state.places} />
}
}
class Child extends React.Component {
componentDidMount() {
console.log('Check access places array', this.props.places)
}
render() {
return <div>Child</div>
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Don't import App into Child. In App, use React's render method with JSX to declare an instance of child. In App's Child JSX, the attributes will become available as "props" within Child. See https://reactjs.org/docs/components-and-props.html React expects a programmatic structure that's not as "free" as straight JS, but React then provides a concise, integrated way to make widgets and SPAs.
you need to export place from App
export const places = [];
And also in child.app
import React from 'react'
import { places } from '../App'
class Child extends React.Component {
componentDidMoint(){
console.log('Check access places array',places)
}
render(){
bla-bla...
}
Related
I have a Bluetooth class and listener method. I want to update my state in Bluetooth class and i will show in functional component.
JavaScript Class
import React, { Component } from "react";
import { MySampleContext } from "../../contexts/MySampleContext";
export class BluetoothClass extends Component {
static contextType = MySampleContext;
sampleBluetoothListener(value){
this.context.updateMyState(value);
}
}
This is my error.
TypeError: undefined is not an object (evaluating 'this.context.updateMyState')
Yes you can, you can pass data down to your component tree using Context API.
// Context file
import React from 'react';
const FormContext = React.createContext();
export default FormContext;
// Parent Class Component
import FormContext from "../context";
class ParentClass extends Component {
state = { name: "John Doe" };
render() {
return (
<FormContext.Provider value={this.state.name}>
<ChildClass />
</FormContext.Provider>
);
}
}
// Child Class Component
import FormContext from "../context";
class ChildClass extends Component {
render() {
return (
<FormContext.Consumer>
{(context) => {
console.log(context);
}}
</FormContext.Consumer>
);
}
}
The value prop in the context API takes an object, in which you could add a method that changes your state and pass it down to your component tree.
I advice you to take a quick look at the official Context API docs by React for a better understanding.
Thanks for all answers. But i mean pure "javascript class" not component, without rendering and react hooks is component based. Finally i solve problem with call back functions.
I have this problem where I want to update my component FooBar if Foo's state changes. How can I do it? This doesn't work.
import React from "react"
import ReactDOM from "react-dom"
import FooBar from "./FooBar"
class Foo extends React.Component {
constructor() {
super()
this.state = { data: [] }
}
changeData() {
someCode
}
render() {
return (
some html
)
}
}
ReactDom.render(<Foo />, document.getElementById('Something'))
ReactDom.render(<FooBar data={this.state.data}/>, document.getElementById('SomethingElse'))
Question is a bit confusing, You can try this if it works
changeData = () =>
this.setState({data:'your changes'})
}
the above code will update the state, thus rest of component connected with class will render automatic.
Create a parent component, render both foo and foobar inside. now you can use state normally for communication between them and only have to use one ReactDom.Render
class Parent extends React.Component{
render(){
return(
<div>
<Foo/>
<Foobar/>
</div>
);
}
}
ReactDom.render(<Parent />, document.getElementById('Something'))
This is all my code below .
When I run it I receive this error (TypeError: Cannot read property 'todos' of null )todos not found at this line var todos=this.state.todos;
My App.js file
import React, { Component } from 'react';
class App extends Component {
getInitialState (){
return{
todos:['washup',"hi","hello","up"]
}
}
render() {
var todos=this.state.todos;
Added Code here
todos=todos.map(function(item,index){
return(
<li>item</li>
);
}
);
Till here
return (
<div id="App">
<ul>{todos}</ul>
)
} )
</div>
);
}
}
export default App;
This is my index.js file
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from `'./registerServiceWorker';`
ReactDOM.render(<div>
<App>Here is my Buttonas</App>
</div>, document.getElementById('root'));
registerServiceWorker();
EDIT
New Error
TypeError: Cannot read property 'map' of undefined
At this line todos=todos.map(function(item,index){
What is the error now?
getInitialState() is only used with createReactClass(). When using ES6 classes you just set state as a property:
See Setting the Initial State in the react docs:
In ES6 classes, you can define the initial state by assigning
this.state in the constructor:
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos: ['washup',"hi","hello","up"],
}
}
// ...
}
or just
class App extends Component {
state = {
todos: ['washup',"hi","hello","up"],
}
// ...
}
With createReactClass(), you have to provide a separate
getInitialState method that returns the initial state:
var App = createReactClass({
getInitialState: function() {
return {
todos: ['washup',"hi","hello","up"],
};
},
// ...
});
You're initializing the state older way in a newer version of reactjs. I already appreciate the answer of trixn. But here's also a solution without removing your current code:
class App extends Component {
state = getInitialState (){
return{
todos:['washup',"hi","hello","up"]
}
}
Notice that I have assigned state to the getInitialState and will work fine because this returns the object {todos:['washup',"hi","hello","up"]} which is similar to this:
state = {todos:['washup',"hi","hello","up"]}
Next, when your component is being rendered first time your todos might get undefined as you stated. To resolve this issue you may add a condition:
todos && todos.length && todos.map(...)
Now, the map function will only run if the todos is not undefined and it has length ie. it has at least one value.
It caused because you didn't define todos in your state, to achieve the soloution, make a constructor in your class and set a todos variable in your state, you can set in empty or null in the constructor and fill it later, then you can use it in your render section, comment if you need further information and also read react life cycle in the official website
With createClass you can use getInitialState:
const App = React.createClass({
getInitialState() {
return { /* initial state */ };
},
});
but with ES6 classes you do like this:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {todos:['washup',"hi","hello","up"]};
}
}
EDITED: get items through map:
class App extends Component {
state={
todos: ['washup', "hi", "hello", "up"]
}
render() {
var todos= this.state.todos.map((item)=>{
return <li>{item}</li>
})
return (
<div id="App">
<ul>{todos}</ul>
</div>
)
}
}
Try this. You should define you todos in the state
App.Js
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor(props) {
super(props);
this.state ={
todos:['washup',"hi","hello","up"]
}
}
render() {
return (
<div id="App">
<ul>{this.state.todos}</ul>
</div>
);
}
}
export default App;
I want to know If I can do this in react, I want to call a function or method of a react component from a JS file, so I could change the state of that component.
I have these three files for example
First App.js
import React,{Component} from 'react';
import Login from './Login';
class App extends Component{
constructor(){
super();
this.state = {session:false}
}
changeStateSession(state_session){
this.setState({session:state_session});
}
render(){
return(
this.state.session
?<div>Content</div>
:<Login/>
);
}
}
Login.js
import React, {Component} from 'react';
import Auth from './Auth.js';
class Login extends Component{
constructor(){
super();
}
login(){
Auth.login();
}
render(){
return(
<button onClick={(e)=>login(e)}></button>
);
}
}
And Auth.js
import App from './../../App.js';
const Auth = {
login:App.changeStateSession(true)
};
export default Auth;
What I really want to know is if theres a way that I could call the App function (changeStateSession) from the Auth.js file, the Auth.js file is just an example of what I would like to achieve I know this file doesn't work, but I would like to know If there is a way to achieve something like this in react, hope you can help me , thanks.
The more common way of doing something like this would be to pass your changeSessionState function as a prop to the Login component.
App.js:
class App extends Component {
constructor(props) {
super(props);
this.state = { session: false }
this.changeStateSession = this.changeStateSession.bind(this);
}
changeStateSession(stateSession){
this.setState({ session: stateSession });
}
render(){
return (
this.state.session
? <div>Content</div>
: <Login onSuccess={() => this.changeStateSession(true)} />
);
}
}
Login.js:
class Login extends Component {
constructor(props) {
super(props);
}
login(){
// If your login process is asynchronous
// and returns a Promise, for example
Auth.login()
.then(this.props.onSuccess);
}
render() {
return (
<button onClick={(e)=> this.login(e)}></button>
);
}
}
Now, when this.props.onSuccess is called once your login succeeds, your App component's state will be updated since your changeStateSession method was passed as a prop to your Login component.
The big takeaway here is that if you want to update a parent's state from a child component, passing functions from your parent component to the child component is the way to typically handle it. No other way of updating parent state from a child is recommended.
Also, if there is an absolute necessity to call the changeStateSession function from your Auth.js file, then it's a very similar concept. Just pass the function through and call it there instead.
You should probably use props. Either calling passing the function to a child component or just passing the value to the App component as a prop and calling the function in the parent component
I am a beginner in react js, before react I was working with angular2 and backbone,and now my problem is I want to create a class such that all of my requests send from this class,like this:
class Ext {
get(url){
$.ajax({
url : url,
success : function(res){},
and ......
});
}
}
in my another component that use from my Ext function :
export default Ext;
import React from 'react';
import {render} from 'react-dom';
import {Ext} from "./module/Ext"
class App extends React.Component {
constructor(props) {
super(props);
/// Ext.get();
}
render () {
return(
<p> Hello React!</p>
);
}
}
render(<App/>, document.getElementById('app'));
how to extends from Ext ??? what is the best way ?
If your get(url) method is something general, it would be wise to have it as part of a separate module, then import and use it in any component you would like.
If, on the other hand, you want to implement a functionality right into a react component, the new ES2015 way of doing it would be by using Composition.
You first create what's called a HOC (Higher order component), which basically is just a function that takes an existing component and returns another component that wraps it. It encapsulates your component and gives it functionality you want, like with mixins but by using composition instead.
So your example would look like something like this:
import React from 'react';
export default const Ext = (Component) => class extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
let result = this.get('some_url').bind(this)
this.setState({ result })
}
get(url) {
$.ajax({
url : url,
success : function(res){
return res;
}
});
}
render() {
// pass new properties to wrapped component
return <Component {...this.props} {...this.state} />
}
};
Then you can just create a stateless functional component and wrap it with the HOC:
import React from 'react';
import Ext from './module/Ext';
class App {
render () {
return <p>{this.result}</p>;
}
}
export default Ext(App); // Enhanced Component
Or using ES7 decorator syntax:
import { Component } from 'react';
import Ext from './module/Ext';
#Ext
export default class App extends Component {
render () {
return <p>{this.result}</p>;
}
}
You can read this post for more details: http://egorsmirnov.me/2015/09/30/react-and-es6-part4.html