i have a problem..
please help me.
i'm working react js
How do I send a state to a conditional react component?
this.state = {
isTrue: false,
name: undefined
}
handleClick(e){
this.setState({
isTrue: true,
name: 'adwin'
})
}
//////// render return ///////
{this.state.isTrue ? (
<App2 name={this.state.name} />
) : ''
}
////// in App2 component //////
componentDidMount(){
console.log(this.props.name) //>>> it work undefined
}
The way you are passing prop to the child component is correct. You can try to pass props as an argument in the constructor of the child component like
class App extends React.Component {
constructor() {
super();
this.state = {
isTrue: false,
name: undefined
}
}
handleClick = (e) => {
this.setState({
isTrue: true,
name: 'adwin'
})
}
render() {
return (
<div>
{this.state.isTrue ? (
<App2 name={this.state.name} />
) : ''
}
<button onClick={this.handleClick}>Click</button>
</div>
)
}
}
class App2 extends React.Component {
constructor(props) {
super(props);
}
componentDidMount(){
console.log(this.props.name)
}
render() {
return (
<div>
{this.props.name}
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
if you're only looking for a conditional you can do {this.state.isTrue && <App2 name={this.state.name} />}
Related
I am new to React.js here. I want to pass selectedMonth state value (from Header.js) to Api create function in (App.js). There is a dropdown in the Header.js. The selectedMonth will be calculated using dropdown value. In the App.js, need to filter my data in Api.create(). Not sure how to add it using props.Can anyone help on this?
Header.js
class Header extends Component {
constructor(props) {
super(props);
this.state = {
value: ''
selectedMonth: formatMonth(defaultMonth)
};
this.onChange = this.onChange.bind(this);
}
onChange(event) {
this.setState({selectedMonth: formatMonth(event.value) });
}
render() {
return (
<header className="header">
<Dropdown className="dropdown-month" value={this.state.value}/> '''this is the dropdown for month and the selectedMonth will be calculated from the dropdown value'''
</div>
</header>
);
}
}
export default Header;
App.js
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
};
}
getWOT() {
Api.create().getWOT().then(res => { '''want to add selectedMonth here'''
if (res.ok) {
if (res.data) {
const data = res.data.Result;
}
else {
window.alert(res.problem)
}
}
})
}
render() {
const renderusers = _.map(this.state.allWOT, (value) => (
<div className="line-bars">
<div className="bar-title">Total Reject</div>
<div className="container">
</div>
</div>
));
return (
this.state.isLoading ?
<h3 style={{ textAlign: 'center' }}>loading...</h3>
:
<div>
<Header />
<div className="grid-container">
<div className="main-grid">
</div>
{renderusers}
</div>
</div>
);
}
}
export default App;
I had moved the value and selectedMonth state to App. js.
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
allWOT: [],
value: defaultMonth,
selectedMonth: formatMonth(defaultMonth),
};
this.onChange = this.onChange.bind(this);
}
onChange(event) {
this.setState({ value: event.value, selectedMonth: formatMonth(event.value) });
}
Then, return
<Header value={this.state.value} onChange={this.onChange}/>
And in Header.js just return Dropdown with value and onChange of this.props
<Dropdown className="dropdown-month" options={months} value={this.props.value} onChange={this.props.onChange} />
I was going through react official documentation when I struck upon an example which updates the parent component through child component callbacks. I was able to understand how the flow works. However, when I tried to optimize the code further it failed to update the component via callbacks.
The Original Code:
https://codepen.io/gaearon/pen/QKzAgB?editors=0010
My code change:
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
this.button = <MyButton message="Login" onClick={this.handleLoginClick} />;
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
if (isLoggedIn) {
this.button = <MyButton message="Logout" onClick={this.handleLogoutClick} />;
} else {
this.button = <MyButton message="Login" onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{this.button}
</div>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
class MyButton extends React.Component {
constructor(props) {
super(props);
this.message=props.message;
this.click=props.onClick;
}
render() {
return (
<button onClick={this.click}>
{this.message}
</button>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
Ok the main problem here is that you are trying to assign to many things to "this".
React does not track changes and re-renders when component's method or properties changes.
try to avoid this pattern and use state and props directly.
Only changes to state or props will cause a component to re-render.
In you situation you can look at this code:
class LoginControl extends React.Component {
state = {isLoggedIn : false}
handleLoginClick = () => {
this.setState({isLoggedIn: true});
}
handleLogoutClick = () => {
this.setState({isLoggedIn: false});
}
button = () => {
const message = this.state.isLoggedIn ? "Logout" : "Login";
const onClick = this.state.isLoggedIn ? this.handleLogoutClick : this.handleLoginClick;
return <MyButton message={message} onClick={onClick} />
}
render() {
return (
<div>
<Greeting isLoggedIn={this.state.isLoggedIn} />
{this.button()}
</div>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
class MyButton extends React.Component {
constructor(props) {
super(props);
this.message=props.message;
this.click=props.onClick;
}
render() {
return (
<button onClick={this.props.onClick}>
{this.props.message}
</button>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
I am learning the concept of States in React. I am trying to understand the difference between using this.handleChange, and this.state.handleChange.
I would be grateful if someone could explain to me, the exact difference between the two, and why would this.state.handleChange not work?
class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
return (
<div>
< GetInput input={this.state.inputValue} handleChange={this.handleChange} />
{ /* this.handleChanges, and this.state.handleChanges */ }
< RenderInput input={this.state.inputValue} />
</div>
);
}
};
class GetInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Get Input:</h3>
<input
value={this.props.input}
onChange={this.props.handleChange}/>
</div>
);
}
};
class RenderInput extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h3>Input Render:</h3>
<p>{this.props.input}</p>
</div>
);
}
};
You can technically call this.state.handleChange so long as you add handleChange in your state.
But it doesn't really make sense since you don't want React to keep a track of it, and it will probably not change (unless you are doing some clever tricks).
constructor(props) {
super(props);
this.state = {
handleChange: e => {
e.preventDefault();
console.log("this.state.handleChange");
}
};
}
One would normally declare a member function in a class.
handleChange = e => {
e.preventDefault();
console.log("this.handleChange");
};
Here is the full working code
(working demo available on CodeSandBox).
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
handleChange: e => {
e.preventDefault();
console.log("this.state.handleChange");
}
};
}
handleChange = e => {
e.preventDefault();
console.log("this.handleChange");
};
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={this.handleChange}>this.handleChange</button>
<button onClick={this.state.handleChange}>
this.state.handleChange
</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
When you say this.state.something this means something is in the state field of the class. When you say this.someFunction this means something is in the class itself. this here is pointing out our class.
class App extends React.Component {
state = {
something: "Something",
}
someFunction = () => console.log(this.state.something);
render() {
return (
<div>
<button onClick={this.someFunction}>Click</button>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById("app")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
So, you can't use this.state.handleChange since there is no handleChange in the state. It is a function belongs to the class. This is why we use this.handleChange.
you can store a function in state
constructor(super){
super(props)
this.state = {
generateANumber: () => this.setState({ number: Math.floor(Math.random() * 100) }),
number: 0
}
}
then if you want to call it in your render method
render() {
return <p> {this.state.number} <button onClick={() => this.state.generateANumber()} Press Me To Generate A New Number </button> </p>
}
This is the concept of storing a function in state. This.function just means the function belongs to that class so you can use it using the this keyword.
I'm trying to call a simple method from the grandparent component in my child component but from some reason I can't , I tried every possible way but I think I'm missing something
here's the full code :
import React, { Component } from 'react';
import './App.css';
var todos = [
{
title: "Example2",
completed: true
}
]
const TodoItem = (props) => {
return (
<li
className={props.completed ? "completed" : "uncompleted"}
key={props.index} onClick={props.handleChangeStatus}
>
{props.title}
</li>
);
}
class TodoList extends Component {
constructor(props) {
super(props);
}
render () {
return (
<ul>
{this.props.todosItems.map((item , index) => (
<TodoItem key={index} {...item} {...this.props} handleChangeStatus={this.props.handleChangeStatus} />
))}
</ul>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
todos ,
text :""
}
this.handleTextChange = this.handleTextChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChangeStatus = this.handleChangeStatus(this);
}
handleTextChange(e) {
this.setState({
text: e.target.value
});
}
handleChangeStatus(){
console.log("hello");
}
handleSubmit(e) {
e.preventDefault();
const newItem = {
title : this.state.text ,
completed : false
}
this.setState((prevState) => ({
todos : prevState.todos.concat(newItem),
text : ""
}))
}
render() {
return (
<div className="App">
<h1>Todos </h1>
<div>
<form onSubmit={this.handleSubmit}>
< input type="text" onChange={this.handleTextChange} value={this.state.text}/>
</form>
</div>
<div>
<TodoList handleChangeStatus={this.handleChangeStatus} todosItems={this.state.todos} />
</div>
<button type="button">asdsadas</button>
</div>
);
}
}
export default App;
The method im trying to use is handleChangeStatus() from the App component in the TodoItem component
Thank you all for your help
This line is wrong:
this.handleChangeStatus = this.handleChangeStatus(this);
//Change to this and it works
this.handleChangeStatus = this.handleChangeStatus.bind(this);
When I click on button, I see '1' in console, but never see '2'. Why it happens? Can you help me please to resolve this issue? I realy dont know why my second component doesn't update.
class App extends PureComponent {
constructor() {
super();
this.state = {
name: 'Vasya'
}
this._onChange = this._onChange.bind(this);
}
_onChange(name) {
this.setState({
name: name
});
}
render() {
console.log(1);
return {
<div>
<Button onClick={this._onChange('Petr')} />
<AnotherComponent username={this.state.name} />
</div>
}
}
}
class AnotherComponent extends PureComponent {
const {
username
} = this.props
render() {
console.log(2);
return {
<div>
test
</div>
}
}
}
export default App;
A few code problems in your example!
when you return your React elements from render(), they must be wrapped in parens () not curlies {}
use React.Component, not React.PureComponent, or you'll get issues
<Button> isn't a thing, use <button>
The main problem then is an infinite loop - when you render, this line:
<Button onClick={this._onChange('Petr')} />
...this calls the _onChange() function at render time and passes the result to Button as the onClick prop. This isn't what you want - you want the onClick prop to be a function that calls _onChange(). So
<button onClick={ () => this._onChange('Petr')} />
Full working example:
class App extends React.Component {
constructor() {
super();
this.state = {
name: 'Vasya'
}
this._onChange = this._onChange.bind(this);
}
_onChange(name) {
this.setState({
name: name
});
}
render() {
console.log(1);
return (
<div>
<button onClick={ () => this._onChange("Petr") } />
<AnotherComponent username={this.state.name} />
</div>
);
}
}
class AnotherComponent extends React.Component {
render() {
console.log(2);
return (
<div>
test
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app") );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>