How to display value of JSX function in Reactjs - javascript

I am quite new to jsx and while making my first Reactjs project today, I am facing this issue where I am unable to display the value of a function in the render method.
This is my parent page (Homescreen.jsx)
(I have commented on the sections where I felt that I have gone wrong)
import React, { Component } from 'react';
import Items from './Items'
class Render extends Component {
render() {
return (
<div>
<Items number="This is the first item !" /> {/*This is where I am adding props to Items*/}
<br>
<Items number="This is the second item !" />
</div>
);
}
}
export default Render;
This is the child page (Items.jsx)
import React, { Component } from 'react';
class Items extends Component {
// This is where I attempted to get the prop
Items = (props) => {
return (
<p>{props.number}</p>
)
}
render() {
return (
<div className="form-group">
{this.Items} {/*This is where I tried to display the output of "number" prop*/}
</div>
);
}
}
export default Items;
The end result is that the "Items" function has no output and I am getting an output which is the same as the output before adding the "Items" function.

Just use this.props.number in render method. (you can access all props from this.props). Try the snippet, there are two ways shown here.
class Items extends React.Component {
Items2 = (props) => {
return (
<p>{props.number}</p>
)
}
render() {
return (
<div className="form-group">
{this.props.number}
{/* alternatively */}
{this.Items2(this.props)}
</div>
);
}
}
class Render extends React.Component {
render() {
return (
<div>
<Items number="This is the first item !" />
<br/>
<Items number="This is the second item !" />
</div>
);
}
}
ReactDOM.render(<Render />, document.getElementById("app"))
<script crossorigin src="https://unpkg.com/react#17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Related

to display a different component with each click (using hooks)

I want to display a different component with each button click.
I'm sure the syntax is wrong, can anyone help me? The browser doesn't load
I would love an explanation of where I went wrong
One component (instead of HomePage) should display on the App component after clicking the button. Help me to understand the right method.
Thanks!
App.js
import React, {useState} from 'react';
import './App.css';
import Addroom from './components/Addroom.js'
import HomePage from './components/HomePage.js'
function App() {
const [flag, setFlage] = useState(false);
return (
<div className="App">
<h1>My Smart House</h1>
<button onClick={()=>{setFlage({flag:true})}}>Addroom</button>
<button onClick={()=>{setFlage({flag:false})}}>HomePage</button>
{setState({flag}) && (
<div><Addroom index={i}/></div>
)}
{!setState({flag}) && (
<div><HomePage index={i}/></div>
)}
</div>
)
}
export default App;
HomePage
import React from 'react'
export default function HomePage() {
return (
<div>
HomePage
</div>
)
}
Addroom
import React from 'react'
export default function Addroom() {
return (
<div>
Addroom
</div>
)
}
I didn't test it but as i can see it should be something like this:
<button onClick={()=>setFlage(true)}>Addroom</button>
<button onClick={()=>setFlage(false)}>HomePage</button>
{flag && (
<div><Addroom index={i}/></div>
)}
{!flag && (
<div><HomePage index={i}/></div>
)}
You need to call setFlage function with argument of Boolean saying true or false and it changes the flag variable that you want to read.
Try the following.
function App() {
const [flag, setFlage] = useState(false);
return (
<div className="App">
<h1>My Smart House</h1>
<button
onClick={() => {
setFlage(true);
}}
>
Addroom
</button>
<button
onClick={() => {
setFlage(false );
}}
>
HomePage
</button>
{flag ? <Addroom /> : <HomePage /> }
</div>
);
}
You are missing render methods and also you should use setState for reactive rendering.( when you use state variables and once value changed render method will rebuild output so this will load your conditinal component.
https://jsfiddle.net/khajaamin/f8hL3ugx/21/
--- HTML
class Home extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div> In Home</div>;
}
}
class Contact extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div> In Contact</div>;
}
}
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = {
flag: false,
};
}
handleClick() {
this.setState((state) => ({
flag: !state.flag,
}));
console.log("hi", this.state.flag);
}
getSelectedComp() {
if (this.state.flag) {
return <Home></Home>;
}
return <Contact></Contact>;
}
render() {
console.log("refreshed");
return (
<div>
<h1>
Click On button to see Home component loading and reclick to load back
Contact component
</h1
<button onClick={() => this.handleClick()}>Switch Component</button>
{this.getSelectedComp()}
</div>
);
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"));

React HOC with multiple components

I want to create a React HOC that would ideally receive two components instead of one wrapped component and toggle between them. That is, in the code below, instead of <h3>component one</h3> and <h3>component two<h3>, they would each represent child components. How would I be able to accomplish this? Some psuedo code for how I would write this HOC:
<HOC>
<ComponentOne />
<ComponentTwo />
</HOC>
<HOC
componentOne={<ComponentOne />}
componentTwo={<ComponentTwo />}
/>
hoc(componentOne, componentTwo)
class HOC extends React.Component {
constructor() {
super();
this.state = {
onClick: false,
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({onClick: !this.state.onClick});
}
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me!</button>
{
this.state.onClick ?
<h3>component one</h3> :
<h3>component two</h3>
}
</div>
);
}
}
ReactDOM.render(<HOC />, app);
<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="app"></div>
I am not sure if I understood you. Why do you need it to be HOC?
If you would pass components as props like that:
<HOC
componentOne={<ComponentOne />}
componentTwo={<ComponentTwo />}
/>
Then you would be able to access them using props.
render() {
return (
<div>
<button onClick={this.handleClick}>Click Me!</button>
{
this.state.onClick ?
this.props.componentOne :
this.props.componentTwo
}
</div>
);
}
If a component has more than one child then this.props.children will be an array.
class HOC extends React.Component {
// ... rest of code ....
render() {
const { onClick } = this.state;
const { children } = this.props;
return !onClick ? children[0] : children[1];
}
}
Then use it like so:
<HOC>
<div>Child One</div>
<div>Child Two</div>
</HOC>
Obviously this will only work with two children but you could extend it by passing an integer to <HOC> through props to tell it what child to select.
Edit
After a quick look at the docs this is a better version of what I wrote above as this.props.children is not an array, it is an opaque data structure:
class HOC extends React.Component {
// ... rest of code ...
render() {
const { onClick } = this.state;
const children = React.Children.toArray(this.props.children);
return !onClick ? children[0] : children[1];
}
}

Moving data between react components

So I'm trying to break the component on my App.js into a smaller component, that being my Sidebar.js. I took a small section of the code and put it in its own Sidebar.js file but no matter what I've tried, I cant call my function getNotesRows() from App.js without it being unable to find it or this.states.notes being undefined.
I just want it to send the code back and forth. This is a demo app, so I know it's not the most practical.
import React, { Component } from "react";
import classNames from "classnames";
import logo from "./logo.svg";
import checkMark from "./check-mark.svg";
import "./App.css";
import Sidebar from "./components/Sidebar.js";
class App extends Component {
constructor(props) {
super(props);
this.state = {
notes: [],
currentNoteIndex: 0
};
this.markAsRead = this.markAsRead.bind(this);
this.selectNote = this.selectNote.bind(this);
console.log("Test started 2.25.19 19:23");
}
componentWillMount() {
fetch('/notes')
.then(response => response.json())
.then(
notes => {
this.setState({
notes: notes,
currentNoteIndex: 0
})
}
)
.catch(
error => {
console.log('Ooops!');
console.log(error);
}
);
}
markAsRead() {
this.setState(currentState => {
let marked = {
...currentState.notes[currentState.currentNoteIndex],
read: true
};
let notes = [...currentState.notes];
notes[currentState.currentNoteIndex] = marked;
return { ...currentState, notes };
});
}
selectNote(e) {
this.setState({ currentNoteIndex: parseInt(e.currentTarget.id, 10) });
}
getTotalUnread() {
let unreadArray = this.state.notes.filter(note => {
return note.read === false;
})
return unreadArray.length;
}
getNotesRows() {
return this.props.notes.map(note => (
<div
key={note.subject}
className={classNames("NotesSidebarItem", {
selected:
this.props.notes.indexOf(note) === this.props.currentNoteIndex
})}
onClick={this.selectNote}
id={this.props.notes.indexOf(note)}
>
<h4 className="NotesSidebarItem-title">{note.subject}</h4>
{note.read && <img alt="Check Mark" src={checkMark} />}
</div>
));
}
// TODO this component should be broken into separate components.
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Notes Viewer Test App</h1>
<div>
Unread:
<span className="App-title-unread-count">
{this.getTotalUnread()}
</span>
</div>
</header>
<div className="Container">
<Sidebar />
<section className="NoteDetails">
{this.state.notes.length > 0 && (
<h3 className="NoteDetails-title">
{this.state.notes[this.state.currentNoteIndex].subject}
</h3>
)}
{this.state.notes.length > 0 && (
<p className="NoteDetails-subject">
{this.state.notes[this.state.currentNoteIndex].body}
</p>
)}
{this.state.notes.length > 0 && (
<button onClick={this.markAsRead}>Mark as read</button>
)}
{this.state.notes.length <= 0 && (
<p>
No Notes!
</p>
)}
</section>
</div>
</div>
);
}
}
export default App;
Above is my App.js
and below is the Sidebar.js that I'm trying to create
import React, { Component } from "react";
import "../App.css";
import App from "../App.js";
class Sidebar extends React.Component{
constructor(props) {
super(props);
}
render(){
return (
<section className="NotesSidebar">
<h2 className="NotesSidebar-title">Available Notes:</h2>
<div className="NotesSidebar-list">{App.getNotesRows()}</div>
</section>
)}}
export default Sidebar;
You cannot access a method like that. You need to pass the method as a prop and use it in the child.
<Sidebar getNotesRows={this.getNotesRows} />
and in Sidebar use
<div className="NotesSidebar-list">{this.props.getNotesRows()}</div>
In your sidebar, you're trying to call getNotesRows() from App, but Sidebar doesn't need access to app (you shouldn't have to import App in Sidebar.js). Instead, you should pass the function from App to your Sidebar component, and reference it from Sidebar's props.
In App.js, you'll need to bind getNotesRows and pass it to sidebar.:
<Sidebar getNotesRows={ this.getNotesRows } />
Then in Sidebar.js, you'll need to reference getNotesRows in your render method:
render() {
const notes = this.props.getNotesRows();
return (
<section className="NotesSidebar">
<h2 className="NotesSidebar-title">Available Notes:</h2>
<div className="NotesSidebar-list">{ notes }</div>
</section>
);
}
It seems like the problem here is that you are trying to use a class function as a static property, to put it simply, you have not initialized the App class when you import it into your sidebar(?), thus no static function was found on your App class so you can call App.getNotesRows() maybe you should re-think your components and separate them in container-components using a Composition Based Programming approach instead of OO approach.

How does this React code translate to class representation?

I'm trying to understand how the code below, which is from Redux examples TODOMVC, can be written using the class notation.
The code is
const App = ({todos, actions}) => (
<div>
<Header addTodo={actions.addTodo} />
<MainSection todos={todos} actions={actions} />
</div>
I tried the following but it doesn't work, I get Warning: App(...): When calling super() inApp, make sure to pass up the same props that your component's constructor was passed.
class App extends React.Component {
constructor({todos, actions}) {
super({todos, actions});
this.todos = todos;
this.actions = actions;
}
render() {
return(
<div>
<Header addTodo={this.actions.addTodo} />
<MainSection todos={this.todos} actions={this.actions} />
</div>
)
}
}
Whatever is passed to App is props. And ({ todos, actions }) is just destructuring from props. This should work:
class App extends React.Component {
render() {
const { todos, actions } = this.props;
return(
<div>
<Header addTodo={actions.addTodo} />
<MainSection todos={todos} actions={actions} />
</div>
)
}
}
By setting this.todo = todos in constructor, you're setting an instance level property. Which means if the props changes later, Header and MainSection will not be updated.
You can simply do what React asks, pass the whole props to the superclass and get out the properties you want explicitly
class App extends React.Component {
constructor(props) {
super(props);
this.todos = props.todos;
this.actions = props.actions;
}
render() {
return(
<div>
<h1>Actions: {this.actions}</h1>
{/*<Header addTodo={this.actions.addTodo} />
<MainSection todos={this.todos} actions={this.actions} />*/}
</div>
)
}
}
ReactDOM.render(<App todos={[]} actions={'some action'} />, 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>

How to update the props of a rendered react component from App.js?

I have a React component MoviesGallery.js with the following configuration:
class MoviesGallery extends Component {
constructor(props) {
super(props)
this.state = { currentImage: 0 };
this.closeLightbox = this.closeLightbox.bind(this);
this.openLightbox = this.openLightbox.bind(this);
this.gotoNext = this.gotoNext.bind(this);
this.gotoPrevious = this.gotoPrevious.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({movies_genre: nextProps.movies_genre})
}
I have rendered the component in my main App.js file like so:
class App extends Component {
render() {
return (
<MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
<div className="App">
<header className="App-header">
<h1 className="App-title">Welcome to React</h1>
<RaisedButton primary={true} label="Query" className="header_buttons"/>
<RaisedButton secondary={true} label="Reset" className="header_buttons"/>
</header>
<MoviesGallery/>
</div>
</MuiThemeProvider>
);
}
}
I want to update the props of my MoviesGallery component without recreating the component. Since I already added the componentWillReceiveProps() to MoviesGallery component, how can I make it so when 'Query' button is clicked, it will pass new props to the already rendered MoviesGallery and componentWillReceiveProps() should cause it to re-render since the state will change.
Just confused about the function that will change the props themselves on-click of the rendered MoviesGallery component.
Thanks in advance!
When a parent pass a new (value) prop to the child, the child component will call the render method automatically. There is no need to set a local state inside the child component to "store" the new prop.
Here is a small example of a Counter that receives a count prop and just displays it, while the parent App in this case will change the value in its state and pass the new value to Counter:
class Counter extends React.Component {
render() {
const { count } = this.props;
return (
<div>{count}</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
onClick = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
const { count } = this.state;
return (
<div>
<Counter count={count} />
<button onClick={this.onClick}>Add to counter</button>
</div>);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<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="root"></div>
you can use the 'state' for your MovieGallery.js props because the state is an object that changes and you must your code like below :
class App extends Component {
state = {
query : null
}
myFunction(query){
this.setState({query});
}
render() {
return (
<MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
<div className="App">
<header className="App-header">
<h1 className="App-title">Welcome to React</h1>
<RaisedButton primary={true} label="Query" className="header_buttons" onClick={this.myFunction = this.myfunction.bind(this)}/>
<RaisedButton secondary={true} label="Reset" className="header_buttons"/>
</header>
<MoviesGallery newProps = {this.state.query}/>
</div>
</MuiThemeProvider>
);
}
}
i hope it helps

Categories