In order to study the react framework, I've been developing a simple web application to rate books. It's currently looking like this:
And the idea of the side bar is simple enought: it's width will be 0 when hidden, and when I click a open menu button it will be set to another width.
The code behind it all is looking like this:
import React from 'react';
import { Link } from 'react-router-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import home from '../../image/side-nav/home.png';
import list from '../../image/side-nav/list.png';
import '../../css/SideNavBar.css'
import * as utils from '../../scripts/utils.js';
const SideNavBar = () =>{
return(
<Router>
<div>
<span className="spanOpen" onClick={utils.openNav()}>☰</span>
<div className="sidenav">
<a className='closebtn' onClick={utils.closeNav()}>×</a>
<ul>
<li>
<Link to='/'><img src={home} alt='Home' /><span className='h-item'>Home</span></Link>
</li>
<li>
<Link to='/books'><img src={list} alt='Books' /><span className='b-item'>Books</span></Link>
</li>
</ul>
<div className='sidenav-footer'>
<hr />
<small>Pelicer © 2018</small>
</div>
</div>
</div>
</Router>
);
}
export default SideNavBar;
And here is the code of the util.js file, which contains the the fucntions to change:
export function openNav() {
// document.getElementsByClassName("sidenav")[0].style.width = "315px";
}
export function closeNav() {
// document.getElementsByClassName("sidenav")[0].style.width = "0";
}
But when I run it, I get the error: TypeError: Cannot read property 'style' of undefined. It happens because it is trying to change the width of somethings that has not yet been created. What I want to do, and tried using componentDidMount, is to import the JavaScript after the HTML has been rendered, in a way that when it sets the width, the component is already there. Can someone help out in a solution?
You're calling the utils.xyz functions too soon. This:
<span className="spanOpen" onClick={utils.openNav()}>☰</span>
calls utils.openNav and uses its return value as the value of the onClick. You probably meant:
<span className="spanOpen" onClick={utils.openNav}>☰</span>
(without the ()) to just refer to the function. That will work if utils.openNav doesn't need this to refer to utils during the call. If it does need this to be utils during the call:
<span className="spanOpen" onClick={() => utils.openNav()}>☰</span>
...which defines a function and uses that function as the value of onClick.
In that case where this matters, probably better to change that functional component to a class component, create that function once, and reuse it:
class SideNavBar extends React.Component {
constructor() {
this.openNav = () => utils.openNav();
// ...
}
// ...
}
and then in render:
<span className="spanOpen" onClick={openNav}>☰</span>
Related
I created a survey page, but when someone doesn't have credits I want to show a notification to the user using react-notifications, I've already tested the button and standalone it works, but when I added it to the tag using react-router-dom on an onClick event, the functions runs, but the notifications doesn't appear. Here's the code:
import React, { Component } from 'react';
import 'react-notifications/lib/notifications.css';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import {NotificationContainer, NotificationManager} from 'react-notifications';
class Button extends Component {
createNotification = () => {
return () => {
switch (this.props.auth.credits) {
case 0:
console.log(this.props.auth.credits);
NotificationManager.error('You have no credits', 'Click to close!', 5000, () => {
});
break;
}
};
};
render() {
return (
<div>
<div className="fixed-action-btn">
<Link to="/surveys/new" className="btn-floating btn-large red" onClick={this.createNotification()}>
<i className="material-icons">add</i>
</Link>
</div>
<NotificationContainer/>
</div>
);
}
}
function mapStateToProps({ auth }){
return { auth };
}
export default connect(mapStateToProps)(Button);
So, when I test this on:
import React from 'react';
import Surveys from './surveys/Surveys';
import Button from '../utilities/addButton';
const Board = () => {
return (
<div>
<Surveys />
<Button />
</div>
);
};
export default Board;
It shows the button, and when clicked without credits, it console.logs the 0 credits, but, it just redirects to the referenced page without showing the notification created.
On my side, it doesn't appear an error neither in the terminal nor in the console or network. But still, the notification is processed but not shown.
So my question is: Is it possible to make the notification appear when the tag redirects to the new page, the only way that I see a solutions if it's not possible is making a conditional to stop the tag to make the change, am I wrong?
Thanks in advance.
Sorry if my question is not properly presented or written, is my first question here.
onClick prop for Link accept function reference. so try replacing
<Link to="/surveys/new" className="btn-floating btn-large red" onClick={this.createNotification}>
<i className="material-icons">add</i>
</Link>
This may be a Very Late reply but for those who didnt answer its because Link doesnt accept onCLick... try for html or with react or reactbootstrap package
I have two files. File1 is a class component returning a class using export. File2 is a normal function component. I have a button in File2 I want to use onclick event handler to summon my file1 which I imported in file2.
I'm including parts of my code.
import Comment from './commentForm';
<Button type="button" outline onClick= {***I want to call comment here***}>
Send Feedback
</Button>
Comment is file1 and the button is on file2
Your button should be integrated into a wrapping component, do something like this:
import React, { useState } from 'react'
import Comment from './commentForm';
const MyComponent = () => {
const [displayed, setDisplayed] = useState()
return (
<div>
{ displayed && <Comment /> }
<Button type="button" outline onClick={() => setDisplayed(true)}>
Send Feedback
</Button>
</div>
)
}
export default MyComponent
I assume, you want to call a class component method/s in the click handler of another component,
lets say you have
Class component : AClassComp in File1.jsx
another component (functional or class) : ParentComp in File2.jsx
you can do the below
// File1.jsx
Class AClassComp extends React.Component{
constructor(){ ...... }
someMethod1=()=>{}
someMethod2=()=>{}
...
render(){.....}
}
export default AClassComp;
//File2
import 'AClassComp' from './File1.jsx'
function ParentComp(){
const classCompRef = useRef(null);
const onClickButton= (e)=> {
// you can access the Class comp methods here
// or do what ever you want using the AClassComp instance
classCompRef.current.someMethod1();
}
return (
<>
<AClassComp ref={classCompRef}/>
<Button onClick={onClickButton}
</>
)
}
when you reference a class component it returns its instance .
If you are importing a functional component from another file, you can simply add the variable in the onClick handler. It might be useful to see what 'Comment' actually does?
import Comment from './commentForm';
<Button type="button" outline onClick= {Comment()}>
Send Feedback
</Button>
EDIT: Assuming Comment looks something like this...
const Comment = () -> {
return comment
}
export default Comment
This question already has answers here:
Changing style of a button on click
(6 answers)
Closed 3 years ago.
I am very new to reactjs and javascript in general, and I'm trying to figure out how to get this simple js code to work in my reactjs file. I want the text to turn red onClick.
I have tried: Creating an external js file and importing it using Helmet to insert a tag
import React, { Component } from 'react';
import './about.css';
import logo from './S54 Logo 2.svg';
import { Helmet } from "react-helmet";
import aboutJS from './about';
export default class About extends Component {
render() {
return (
<div id="about-page">
<Helmet>
<script>
{'aboutJS'};
</script>
</Helmet>
<img id="about-page-logo-img" src={logo} />
<h2 id="mission-statement" onclick="myFunction()">
Catalog the World's Underrepresented Art so everyone can share in the enjoyable experience
</h2>
</div>
)
}
}
this was the js file
export function myFunction() {
document.getElementById("mission-statement").style.color = "red";
}
Ive also tried adding that js code straight into the script tag, instead of importing the file but that didn't work.
I tried putting a tag for that external js file I created into the of my index.html file, and calling the function in my reactjs file.
Nothing is working. Where and how should I add this code?
In JSX, props use this syntax: propName={...} with strings being an exception, where you can do propName="...".
So you should just be able to do onClick={myFunction}
Edit: you might have to do onClick={myFunction.bind(this)} to get your desired effect.
Edit: fixed Camel Case
Zelmi, React uses JSX, which means Javascript XML. You can write JS directly into the component like this:
import React, { Component } from 'react';
import './about.css';
import logo from './S54 Logo 2.svg';
import aboutJS from './about';
export default class About extends Component {
myFunction() {
document.getElementById("mission-statement").style.color = "red";
}
render() {
return (
<div id="about-page">
<Helmet>
<script>
{'aboutJS'};
</script>
</Helmet>
<img id="about-page-logo-img" src={logo} />
<h2 id="mission-statement" onclick="myFunction()">
Catalog the World's Underrepresented Art so everyone can share in the enjoyable experience
</h2>
</div>
)
}
}
And thus call the myFunction from anywhere in the page.
You also need to understand how React and the VirtualDOM work, start by reading the docs.
React does not work with the standard html onclick attribute but rather with the React prop onClick, which takes in a function as well, but you need to show React XML that you are calling your JS code by opening a {} code scope like so:
<div id="about-page">
<Helmet>
<script>
{'aboutJS'};
</script>
</Helmet>
<img id="about-page-logo-img" src={logo} />
<h2 id="mission-statement" onClick={this.myFunction}>
Catalog the World's Underrepresented Art so everyone can share in the enjoyable experience
</h2>
</div>
EDIT
You also unfortunately need to bind your function when using React Class component, in the constructor method:
constructor(props) {
super(props);
// This binding is necessary to make `this` work in the callback
this.myFunction = this.myFunction.bind(this);
}
Part of the point of React is to abstract away the DOM so you don't have to do things like getElementById and all that.
A simple way to accomplish what you want to do would be something like this:
export default class About extends Component {
constructor(props) {
super(props);
this.state = {
color: "black"
}
}
myFunction = () => {
this.setState({color: "red"});
}
render() {
return (
<div id="about-page">
<img id="about-page-logo-img" src={logo} />
<h2 onClick={this.myFunction} style={{color: this.state.color}}>
Catalog the World's Underrepresented Art so everyone can share in the enjoyable experience
</h2>
</div>
)
}
}
Note that if your setup doesn't allow arrow functions in class properties, you may have to bind this to the function like so:
constructor(props) {
super(props);
this.state = {
color: "black"
}
this.myFunction = this.myFunction.bind(this);
}
Zelmi, You can import { myFunction } from 'path/to/your/jsfile.js' which allows you to use myFunction any where in your JS file where your component lives.
Also, use onClick instead of onclick, wrap your function with Carely Braces {} instead of Quotes ""
import React, { Component } from 'react';
import './about.css';
import logo from './S54 Logo 2.svg';
import { myFunction } from 'path/to/your/jsfile.js'; //HERE
import { Helmet } from "react-helmet";
import aboutJS from './about';
export default class About extends Component {
render() {
return (
<div id="about-page">
<Helmet>
<script>
{'aboutJS'};
</script>
</Helmet>
<img id="about-page-logo-img" src={logo} />
<h2 id="mission-statement" onClick={myFunction}>
Catalog the World's Underrepresented Art so everyone can share in the enjoyable experience
</h2>
</div>
)
}
}
This should be super simple for some of you. I have a super simple app that I am making to teach myself the glory that is React and reactDom. Currently, I am pulling from an API (which actually works!), however, I am unable to see any data when rendering to the screen. Literally just two components. I am sure that I am using props or state wrong here, I just don't know where. It's possible that my map function is the problem as well.
Here is the code:
Parent:
import React from "react";
import ReactDOM from "react-dom";
import axios from 'axios'
import { Table } from './Table'
export class DataList extends React.Component {
state = {
articles: []
}
componentDidMount() {
axios.get('http://127.0.0.1:8000/api/portblog/')
.then(res => {
this.setState({
articles: res.data
})
console.log(res.data)
})
}
render() {
return(
<div>
<Table id={this.state.articles.id} articles={this.state.articles} />
</div>
)
}
}
export default DataList
And the child:
import React from "react";
import PropTypes from "prop-types";
import key from "weak-key";
export const Table = (props) => (
<div>
<h1>Welcome to the Article List Page Home</h1>
<li>{props.articles.map((article) => {
{article.titles}
})}</li>
</div>
);
export default Table;
The problem is that your map() call is not returning anything. You need to do something like:
<div>
<h1>Welcome to the Article List Page Home</h1>
{props.articles.map(article =>
<li>{article.titles}</li>
)}
</div>
I'm not exactly sure what your desired output is, but generally you map over data to generate a set of dom elements.
The problem is
<li>{props.articles.map((article) => {
{article.titles}
})}</li>
JSX expressions cannot be used in any arbitrary place. props.articles.map(...) is already an expression, so creating a new one wouldn't make sense.
{article.titles} inside a function creates a block that does nothing. Nothing is returned from map callback, the array isn't mapped to anything.
Depending on what should resulting layout look like, it should be either
<li>{props.articles.map((article) => article.titles)}</li>
output titles within single <li> tag, or
{props.articles.map((article) => <li>{article.titles}</li>)}
to output a list of <li> tags.
ESLint array-callback-return rule can be used to prevent the problem with callback return value.
I'm sure im missing some key element of understanding because this file gets exported and used in another file and then that is exported to another file and then that last file in the chain is what is sent to react.DOM. but why can't I make my components in a function in this file and have them be rendered. I'm not understanding something about the chain and how many exported files you can have and how i guess nested they can be.... help please. Cause if I do this at the surface level of the file chain it works fine but not this far down...
import React, { Component } from 'react';
import './Css_files/OfficeComponent.css';
class OfficeComponent extends Component {
pic_span_nurse(props){
return(
<div className="row box_infoz">
<div className="col-xs-3">
<h1>picture</h1>
</div>
<div className="col-xs-9">
<h5>So this has noew changed to the office part where we have staff in this box and directions on the bottom</h5>
</div>
</div>
);
}
render() {
return (
<div>
<pic_span_nurse/>
</div>
);
}
}
export default OfficeComponent;
I am very surprised doing <pic_span_nurse/> works at all, in any context.
I think you're mistaking the concept of what a Component is. A method inside a Component is not considered a component. It is still a method. Which means you have to render pic_span_nurse like you would when you return a method. This should definitely work:
{this.pic_span_nurse()}
The curly braces mean it's JavaScript code that should be interpreted, rather than literal text.
Also, JavaScript style guides encourage (read: must) naming to be done in camelcase, not underscores.
You can either create a separate component and use it in your code.
import React,{Component} from 'react';
import './Css_files/OfficeComponent.css';
const Pic_span_nurse =(props)=>{
return(
<div className="row box_infoz">
<div className="col-xs-3">
<h1>picture</h1>
</div>
<div className="col-xs-9">
<h5>So this has noew changed to the office part where we have staff in this box and directions on the bottom</h5>
</div>
</div>
);
}
class OfficeComponent extends Component {
render() {
let compProps = {};//the props of the Pic_span_nurse component
return (
<div>
<Pic_span_nurse {...compProps}/>
</div>
);
}
}
export default OfficeComponent;
Or you can use a function call to render the necessary html.
import React, { Component } from 'react';
import './Css_files/OfficeComponent.css';
class OfficeComponent extends Component {
pic_span_nurse=(props)=>{
return(
<div className="row box_infoz">
<div className="col-xs-3">
<h1>picture</h1>
</div>
<div className="col-xs-9">
<h5>So this has noew changed to the office part where we have staff in this box and directions on the bottom</h5>
</div>
</div>
);
}
render() {
return (
<div>
{this.pic_span_nurse(this.props)}
</div>
);
}
}
export default OfficeComponent;