on click i want to generate alert in react js method - reactjs

This is my code:
generateAlert = () => {
alert('hi');
}
return <Tile
click={(index)=>{this.generateAlert}}
title={tile.title}
value={tile.value}
key={tile.id}
/>
This is the error I'm getting:
Expected an assignment or function call and instead saw an expression no-unused-expressions
Search for the keywords to learn more about each error.

First, I do wonder if in your Component you have an array of Tile data, and you want to render a Tile for each entry of the array (I thought so because you added the key prop to Tile).
Anyways, I made an example similar to what you want to achieve, and it's working. Look at this:
const Tile = (props) => {
return (
<div className="Tile">
<h3>{props.title}</h3>
<div onClick={props.click}>
{props.value}
</div>
</div>
);
}
class App extends React.Component {
constructor(props) {
super(props);
}
generateAlert = () => {
alert("Hi");
}
render() {
return (
<Tile
click={this.generateAlert}
title={"This isa a Title"}
value={"This is the value"} />
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
#import url(https://fonts.googleapis.com/css?family=Montserrat);
body {
font-family: 'Montserrat', sans-serif;
}
<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>
Now, I may help you in a deeper way if you would post the code of the Component that wants to render Tile; maybe, there are some error in that.

Hei!
If it's a function invocation inside your component's onClick function, you need to add () after this.generateAlert in your component
So it's gonna be like:
return <Tile
click={(index)=>{this.generateAlert()}}
title={tile.title}
value={tile.value}
key={tile.id}
/>
Otherwise, you can use your function as a onClick callback per se.
In that case you need to have it like this:
return <Tile
onClick={this.generateAlert}
title={tile.title}
value={tile.value}
key={tile.id}
/>
Cheers!

I will do in this way:
Q: why I export Tile to new component?
A: As each component should be as short as possible. There is a many advantages to doing in this way
like: "easy to find bugs (testing)".
import React, { Component } from "react";
import Tile from "./Tile";
import "./App.css";
class App extends Component {
constructor(props) {
super(props);
this.generateAlert = this.generateAlert.bind(this);
}
generateAlert = () => {
alert("Hi");
};
render() {
return (
<Tile
click={this.generateAlert}
title={"This isa a Title"}
value={"This is the value"}
/>
);
}
}
export default App;
and file Tile.js:
import React, { Component } from "react";
export default class Tile extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<button onClick={this.props.click}>click me</button>
<p>{this.props.title}</p>
<p>{this.props.value}</p>
</div>
);
}
}
This file Tile.js are ready for future addons but if you want to use only like it is now I would recommend to change into stateless component:
import React from "react";
const Tile = props => {
return (
<div>
<button onClick={props.click}>click me</button>
<p>{props.title}</p>
<p>{props.value}</p>
</div>
);
};
export default Tile;

Related

Call class method from another component

I'm stuck with React what's a new programming environment for me. So probably I use wrong names for certain objects.
I want to call a method in a class in file 'App.jsx' from a component in file 'Navbar.jsx'. This is (part of) my code so far:
App.jsx:
import React, {} from "react";
import { Navbar, Home, Footer, Documentation } from "./components";
class App extends React.Component {
constructor(props)
{
super(props);
this.state = { mainComponent: 'Home' };
}
getClick = () => {
console.log('test');
}
render() {
return (
<div className="min-h-screen gradient-bg-welcome">
<Navbar getClick={this.getClick}/>
<Home/>
<Footer/>
</div>
);
}
}
export default App;
Navbar.jxs:
...
const Navbar = () => {
...
return (
...
<div ... onclick={() => (call getClick in App.jsx here)}>
...
</div>
);
}
export default Navbar;
I searched the internet and tried some code from several examples, but I probably miss something simple. I can't figure out how to call getClick from Navbar.jsx.
I also tried using states, which should be a better option from what I read, but that also didn't work out for me.
My goal:
In App.jsx I have this:
<Navbar/>
<Home/>
<Footer/>
I want, from the Navbar where I have some link texts, to reload/change the component between Navbar and Footer for another component based on what link I click in the Navbar.
Try this
const Navbar = (props) => {
...
return (
...
<div ... onclick={() => props.getClick()}>
...
</div>
);
}
export default Navbar;
What we did here is simple, we simply passed the function as a prop from the parent. And used the passed props to access and call the function.

Why I can't use an imported component inside a functional component in React?

I am new to React. For the code readability, instead of in-line styled button, I want to write it as a separate class component. I created a customed button 'addImageButton'and imported it to another .js file. It doesn't render the customer button when I try to use it within a functional component. How can I make the functional component be able to use the imported button? Thanks!
//addImageButton.js
import React, { Component } from "react";
class addImageButton extends Component {
render() {
return (
<div>
<button
style={{
borderStyle: "dotted",
borderRadius: 1,
}}
>
<span>Add Image</span>
<span>Optional</span>
</button>
</div>
);
}
}
export default addImageButton;
//AddNewTaskButton.js
import React, { Component } from "react";
import Modal from "react-modal";
**import addImageButton from "../addImageButton";**
class AddNewTaskButton extends Component {
constructor(props) {
super(props);
this.state = {
show: false,
};
this.setShow = this.setShow.bind(this);
this.closeShow = this.closeShow.bind(this);
this.addTaskModal = this.addTaskModal.bind(this);
}
setShow() {
this.setState({
show: true,
});
}
closeShow() {
this.setState({
show: false,
});
}
addTaskModal = () => {
return (
<div>
<Modal
isOpen={this.state.show}
onRequestClose={() => this.closeShow()}
>
**<addImageButton />**
</Modal>
</div>
);
};
render() {
return (
<div>
<button onClick={() => this.setShow()}>
<img src={addIcon} alt={text}></img>;
<span>text</span>
</button>
<this.addTaskModal className="modal" />
</div>
);
}
}
export default AddNewTaskButton;
Easier way would be to just use functional components. Also, react components should be upper case, like so:
export default function AddImageButton() {
return (
<div>...</div>
)
}
create a different component for Modal
import Modal from './Modal'
import AddImageButton from './AddImageButton'
function AddTaskModal() {
return (
<div>
<Modal> <AddImageButton/> </Modal>
</div>
)
}
then
import AddTaskModal from './AddTaskModal'
function AddNewTaskButton() {
return (
<div>
<AddTaskModal/>
</div>
)
}
I don't know your file directories, so I just put randomly.
as for your question, try to make the AddImageButton as a class and see if it renders then. If it doesn't it might be due to something else. Do you get errors? Also maybe create the AddTaskModal class separately and render it out as a component. Maybe that'll help

How to switch between Components in React.js

So I am building a React app and got I think a decent idea pf whay I am doing. But I am looking to find how I can switch between components. Each component is its own individual js file.
App.js file:
import React from 'react';
import './App.css';
import MainPage from './mainpage'
function App() {
return (
<div className="App">
<h1>Welcome to Comix Nation </h1>
<MainPage />
</div>
);
}
export default App;
mainpage.js file:
import React from 'react';
import './App.css';
import CreateAccount from './createaccount.js'
import LogIn from './login.js'
import MainMenu from './mainmenu.js'
class MainPage extends React.Component {
constructor(props){
super(props);
this.state = {
currentPage: 'login'
};
}
getPage(currentPage){
const page ={
mainmenu: <MainMenu />,
createaccount: <CreateAccount />,
login: <LogIn />
};
return page[currentPage]
}
switchPage(currentPage){
this.setState({currentPage});
};
render(){
return (
<div>
<div>
<MainMenu switchPages={this.switchPage}/>
</div>
</div>
);
}
}
export default MainPage;
mainmenu.js file:
import React from 'react';
import './App.css';
class MainMenu extends React.Component {
constructor(props){
super(props);
this.state = {page: 'none'}
}
handleSelection(pageSelection){
this.props.switchPage(pageSelection);
}
render(){
return (
<div>
<h2 onClick={()=> this.handleSelection('createaccount')}>Click to create new account</h2>
<h2>Click to log in</h2>
</div>
);
}
}
export default MainMenu;
The idea is that I can click on either the create or login and get the appropriate js file to render.
so, from reading your code it sounds like you want to do routing (judging from your naming convention at least). There are a number of routing libraries you can use to render different pages if you want to use that. If you just want to switch out components, you've almost got it
class MainPage extends React.Component {
constructor(props){
super(props);
this.state = {
currentPage: 'login'
};
}
switchPage(currentPage){
this.setState({currentPage});
};
render(){
return (
<div>
<div>
{
this.state.currentPage === 'login' &&
<Login/>
}
{
this.state.currentPage === 'MainMenu' &&
<MainMenu/>
}
{
this.state.currentPage === 'SignUp' &&
<SignUp/>
}
</div>
</div>
);
}
}
The way react reads this is true and render this component some people prefer to use a ternary and return null but this is cooler imho 😎
There are several ways to do this, if you are trying to avoid react-router-dom you can implement this system fairly easy.
this.state = {
currentComponent: "",
}
this will allow you to keep track of what component is suppose to show. Put this in your controllers state.
showComponent = (component) => {
this.setState({currentComponent: component})
}
Put this in your main controller file, where you import your components that you will use.
Then you set up your components to display depending what is sent in.
let checkCurrentComponent = this.state.currentComponent;
Make a variable to check for easy checking.
{checkCurrentComponent === "topicList" ? (
<TopicTitles
showComponent={this.showComponent}
/>
) : checkCurrentComponent === "author" ? (
<TopicData
showComponent={this.showComponent}
/>
) : checkCurrentComponent === "commentForm" ? (
<CommentForm }
showComponent={this.showComponent}
/>
): null}
Then in your components you can use that function to pass in the name. Here is how I like to do that.
const handleCommentForm = (e, component) => {
e.preventDefault();
props.showComponent(component);
}
This will be at the top of my stateless function.
will bring up my comment form.
Then the button..
<button
className="btn btn-outline-none"
onClick={e => handleCommentForm(e, "commentForm")}
>
Add Comment
</button>

Try to call a component inside a component - React

So I started with React and I have these two Components.
In the first component I want to iterate an array of objects with the map() function (which works) and call the other component that for now just returns a simple h1 tag.
Well, nothing is been called and there is no error in the console.
I believe the problem is in the return sentence in the renderAvatarData()
(if I do console.log after the return sentence it seems to not get there but if the console.log is before the return it invokes)
HomePageBoxesData.js
import React, { Component } from 'react';
import AvatarDetails from './AvatarDetails';
class HomePageBoxesData extends Component{
constructor(props) {
super(props);
};
renderAvatarData(){
this.props.data.map(data => {
return <AvatarDetails data={data}/>
});
}
render(){
return(
<div>
{this.renderAvatarData()}
</div>
);
}
};
export default HomePageBoxesData;
AvatarDetails.js
import React, { Component } from 'react';
class AvatarDetails extends Component{
constructor(props) {
super(props);
};
render(){
return(
<h1>Hello World</h1>
);
}
};
export default AvatarDetails;
Issue is in renderAvatarData() method, you forgot to use return with map, Use this:
renderAvatarData(){
return this.props.data.map((data)=>{
return <AvatarDetails data={data}/>
});
}
Since you just want to return the Component, you can directly write it like this:
renderAvatarData(){
return this.props.data.map(data => <AvatarDetails data={data} /> );
}
i agree with Mayank Shukla but i usually use this method in this case:
render() {
return(
<div>
_.map(this.props.data, function(value, key){
return(
<AvatarDetails key={key} data={value} />
)
})
</div>
i am not sure if there is one better than the other

Wrapping React components in other React components that mange behavior props.

I found this code online and because I'm new to React wanted to know how to use it without getting this error.
this.props.children is not a function
From what I gather its listing to the body scroll position and trying to pass it as props to any React children its wrapped around. Am I correct ?
If so why the above error when I use it like below.
import React, {Component} from 'react';
import Nav from './nav';
import styles from '../../styles/header.scss';
import bgCover from '../../images/homeslider.jpg';
import Scroll from '../utils/scroll';
export default class Header extends Component{
render(){
return(
<Scroll>
<div id='header'>
<div className="container">
<img src={bgCover} id='bg-cover' alt="background-image" />
<div id="temp-text">HEADER</div>
<Nav />
</div>
</div>
</Scroll>
)
}
}
This is the scroll.js file
import React, {Component} from 'react';
export default class Scroll extends Component {
constructor(props) {
super(props);
this.state = { scrollTop: 0,
scrollLeft: 0 };
window.addEventListener('scroll', event => {
this.setState({ scrollTop: document.body.scrollTop,
scrollLeft: document.body.scrollLeft});
});
}
render() {
return this.props.children(this.state.scrollTop, this.state.scrollLeft)
}
}
As Andrew mentions, this.props.children is not a function. In your render function, if you wanted to render the children components, then your render would be written something like this.
render() {
return (
<div>
{this.props.children}
</div>
)
}
In your example, the code above would place this JSX block
<div id='header'>
<div className="container">
<img src={bgCover} id='bg-cover' alt="background-image" />
<div id="temp-text">HEADER</div>
<Nav />
</div>
</div>
into your Scroll component, because they are the children (nested) components.
Now, it looks like you want to pass props to your children components. You can do this by adding accessing React.Children.
An nice example of passing a function as a prop to all children components can be found here :
doSomething: function(value) {
console.log('doSomething called by child with value:', value);
}
const childrenWithProps = React.Children.map(this.props.children,
(child) => React.cloneElement(child, {
doSomething: this.doSomething
})
);
return <div>{childrenWithProps}</div>

Resources