I edited code that was working perfectly fine, until I added new code to make the button clicking work from video to video. I just can't find the error, and the terminal is not picking it up either.
Can someone tell me why the ./video_list_item.js is not being recognized anymore?
Attached is the parent, and 2 child components, though I have 5 total components the error is definitely only in one of the two.
index.js
import React, {Component } from 'react';
import ReactDOM from 'react-dom';
import YTSearch from 'youtube-api-search';
import SearchBar from './components/searchbar';
import VideoList from './components/video_list';
import VideoDetail from './components/video_detail';
const API_KEY = 'AIzaSyAi1CzVpifuFUDVQf3dzrTu3mwJDP2n8r8';
class App extends Component {
constructor(props){
super(props);
//Do i expect this component to play any type of state? aka pass props
this.state= {
videos: [],
selectedVideo:null
};
// ^proper name can be anything
YTSearch({key: API_KEY, term: 'surfboards'}, (videos) => {
// console.log(data);
this.setState({ videos:videos,
selectedVideo: videos[0]
});
}); // this.setState({videos : vidoos});
}
render (){
return (
<div>
<SearchBar />
<VideoDetail video={this.state.selectedVideo} />
<VideoList
onVideoSelect={selectedVideo => this.setState({selectedVideo}) }
videos={this.state.videos} />
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector('.container'));
video_list.js
//video list file. JS.react
import React from 'react';
import VideoListItem from './video_list_item';
const VideoList = (props) => {
// ^props is made args here because videos var is passed
// in index.js into VideoList function(with state).
const videoItems = props.videos.map((video) => {
return (
<VideoListItem
onVideoSelect={props.onVideoSelect}
key={video.etag}
video ={video} />
);
});
return (
<ul className="col-md-4 list-group">
{videoItems}
</ul>
);
};
export default VideoList;
video_list.item.js
//video list item file. JS.react
import React from 'react';
const VideoListItem = ({video, onVideoSelect}) => {
const imageUrl = video.snippet.thumbnails.default.url;
// can see this in console log
return (
<li onClick={() => onVideoSelect{video} }className="list-group-item">
<div className ="video-list media">
<div className ="media-left">
<img className="media-object" src = {imageUrl}/>
</div>
<div className="media-body">
<div className="media-heading"> {video.snippet.title} </div>
</div>
</div>
</li>
);
};
export default VideoListItem;
I can post the error message I get in the dev tools, but it literally just says one thing. This is the error message => Cannot find module "./video_list_item"
Also, no files were moved around at all, the code was edited and that created the error message. Thanks for anyone who sincerely answers this question!
<li onClick={() => onVideoSelect{video} }className="list-group-item">
The error is the {video} should actually be in parenthesis like so (video).
correct code is:
<li onClick={() => onVideoSelect(video) }className="list-group-item">.
Note: The {} makes it so the child component is not recognized by the parent for some strange reason. Thanks to all those who helped in answering!
Related
I am struggling with figuring out how to implement conditional rendering in React. Basically, what I want to do is this: if there is a reviewResponse in the reviewResponses array, I no longer want to render the reviewResponseForm. I only want to render that ReviewResponse. In other words, each review can only have one response in this app.
I am not sure what I am doing wrong when trying to implement this logic. I know I need to implement some kind of conditional statement saying if the length of my reviewResponses array is greater than 0, I need to render the form. Otherwise, I need to render that reviwResponse. Every statement I have written has not worked here. Does anybody have a suggestion?
Here is my code so far:
My review cardDetails component renders my ReviewResponseBox component and passed the specific reviewId as props:
import React from "react";
import { useLocation } from "react-router-dom";
import StarRatings from "react-star-ratings";
import ReviewResponseBox from "../ReviewResponse/ReviewResponseBox";
const ReviewCardDetails = () => {
const location = useLocation();
const { review } = location?.state; // ? - optional chaining
console.log("history location details: ", location);
return (
<div key={review.id} className="card-deck">
<div className="card">
<div>
<h4 className="card-title">{review.place}</h4>
<StarRatings
rating={review.rating}
starRatedColor="gold"
starDimension="20px"
/>
<div className="card-body">{review.content}</div>
<div className="card-footer">
{review.author} - {review.published_at}
</div>
</div>
</div>
<br></br>
{/*add in conditional logic to render form if there is not a response and response if there is one*/}
<ReviewResponseBox review_id={review.id}/>
</div>
);
};
export default ReviewCardDetails;
Then eventually I want this component, ReviewResponseBox, to determine whether to render the responseform or the reviewresponse itself, if it exists already.
import React from 'react';
import ReviewResponse from './ReviewResponse';
import ReviewResponseForm from './ReviewResponseForm';
class ReviewResponseBox extends React.Component {
constructor() {
super()
this.state = {
reviewResponses: []
};
}
render () {
const reviewResponses = this.getResponses();
const reviewResponseNodes = <div className="reviewResponse-list">{reviewResponses}</div>;
return(
<div className="reviewResponse-box">
<ReviewResponseForm addResponse={this.addResponse.bind(this)}/>
<h3>Response</h3>
{reviewResponseNodes}
</div>
);
}
addResponse(review_id, author, body) {
const reviewResponse = {
review_id,
author,
body
};
this.setState({ reviewResponses: this.state.reviewResponses.concat([reviewResponse]) }); // *new array references help React stay fast, so concat works better than push here.
}
getResponses() {
return this.state.reviewResponses.map((reviewResponse) => {
return (
<ReviewResponse
author={reviewResponse.author}
body={reviewResponse.body}
review_id={this.state.review_id} />
);
});
}
}
export default ReviewResponseBox;
Here are the ReviewResponseForm and ReviewResponse components:
import React from "react";
class ReviewResponseForm extends React.Component {
render() {
return (
<form className="response-form" onSubmit={this.handleSubmit.bind(this)}>
<div className="response-form-fields">
<input placeholder="Name" required ref={(input) => this.author = input}></input><br />
<textarea placeholder="Response" rows="4" required ref={(textarea) => this.body = textarea}></textarea>
</div>
<div className="response-form-actions">
<button type="submit">Post Response</button>
</div>
</form>
);
}
handleSubmit(event) {
event.preventDefault(); // prevents page from reloading on submit
let review_id = this.review_id
let author = this.author;
let body = this.body;
this.props.addResponse(review_id, author.value, body.value);
}
}
export default ReviewResponseForm;
import React from 'react';
class ReviewResponse extends React.Component {
render () {
return(
<div className="response">
<p className="response-header">{this.props.author}</p>
<p className="response-body">- {this.props.body}</p>
<div className="response-footer">
</div>
</div>
);
}
}
export default ReviewResponse;
Any advice would be helpful, thank you.
If I understand your question correctly, you want to render ReviewResponseForm if the this.state.reviewResponses state array is empty.
Use the truthy (non-zero)/falsey (zero) array length property to conditionally render either UI element.
render () {
const reviewResponses = this.getResponses();
const reviewResponseNodes = <div className="reviewResponse-list">{reviewResponses}</div>;
return(
<div className="reviewResponse-box">
{reviewResponses.length
? (
<>
<h3>Response</h3>
{reviewResponseNodes}
</>
)
: (
<ReviewResponseForm addResponse={this.addResponse.bind(this)}/>
)}
</div>
);
}
I have a simple react app in which i have to use useContext.
(btw im using vite + react)
here is my code for Context.jsx
import React, {useContext} from 'react';
const emailContext = React.createContext();
export const useEmail = () => useContext(emailContext);
export const emailProvider = ({children}) => {
const currentUser = "None";
const value = {
currentUser
}
return(
<emailContext.Provider value={value}>
{children}
</emailContext.Provider>
)
}
and heres how i am using the context
import "./styles.css";
import { useEmail } from "./Context/Context"
export default function App() {
const {currentUser} = useEmail();
return (
<div className="App">
<h1>Hello CodeSandbox {currentUser}</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
I am sure why I am getting error in this code.
some of the errors that I am getting
_useEmail is undefined (latest)
currentUser user is undefined
thing i have tried
Initialized createContext with some initial value (only intial value is visible).
using useContext() directy in the App.js (useContext(emailContext) return undefined)
instead of {children} used <children/>.
used useState instead of const currentUser in emailProvider
I am getting same problem even when I use typescript.
but none of the above helped.
You should wrapping app with <emailProvider></emailProvider> to using data in value={value}. Now it gets undefined from const emailContext = React.createContext();
Below code may help you analyse the flow , also check link for more details https://medium.com/technofunnel/usecontext-in-react-hooks-aa9a60b8a461
use useContext in receiving end
import React, { useState } from "react";
var userDetailContext = React.createContext(null);
export default function UserDetailsComponent() {
var [userDetails] = useState({
name: "Mayank",
age: 30
});
return (
<userDetailContext.Provider value={userDetails}>
<h1>This is the Parent Component</h1>
<hr />
<ChildComponent userDetails={userDetails} />
</userDetailContext.Provider>
);
}
function ChildComponent(props) {
return (
<div>
<h2>This is Child Component</h2>
<hr />
<SubChildComponent />
</div>
);
}
function SubChildComponent(props) {
var contextData = React.useContext(userDetailContext);
return (
<div>
<h3>This is Sub Child Component</h3>
<h4>User Name: {contextData.name}</h4>
<h4>User Age: {contextData.age}</h4>
</div>
);
}
update: i removed this from this.props. but now nothing is showing in the localhost.
i am trying to write a blog page in react. Here is my blog.js:
import React from 'react'
const Blog=props=>{
const {title,author,content}=this.props
return(
<div>
<h2>{title}</h2>
<h5><i>{author}</i></h5>
<br/>
<h3>{content}</h3>
</div>
)
}
export default Blog
and my App.js is below:
import React,{Component} from 'react';
import Blog from './Blog'
class App extends Component {
render(){
const posts=[
{
title:'First',
author:'Anonymous',
content:'first Post',
},
{
title:'Second',
author:'Anonymous',
content:'Second Post',
},
{
title:'third',
author:'Anonymous',
content:'Second Post',
},
]
return (
<div className="container">
<Blog postData={posts}/>
</div>
);
}
}
export default App ;
while i excute npm start there is no error but in the broswer it is saying:
TypeError: Cannot read property 'props' of undefined
Blog
C:/Myfiles/python/Django/djangorest/booklearn/test-cases/src/Blog.js:5
2 |
3 |
4 | const Blog=props=>{
> 5 | const {title,author,content}=this.props
6 | return(
7 |
8 | <div>
i am running out of options. How can i solve this thing?
i have started reactjs very recent. any advice will be much appreciated.
You are using a functional component and passing in props as an argument to your function (props =>). You do not need to use this.props just props will work.
You are passing in an array of posts under the prop name 'postData'. In your blog component you need to:
import React from 'react'
const Blog=props=>{
return props.postData.map((post) => {
const { title, author, content } = post;
return (
<div key={title}>
<h2>{title}</h2>
<h5><i>{author}</i></h5>
<br/>
<h3>{content}</h3>
</div>
);
});
}
export default Blog;
Remove this since its not a class and props are being passed as the first parameter of the function.
import React from 'react'
const Blog = (props) => {
const { title,author,content } = props;
return(
<div>
<h2>{title}</h2>
<h5><i>{author}</i></h5>
<br/>
<h3>{content}</h3>
</div>
)
}
export default Blog
First of, I'm a newbie at Javascript and React.js as you will probably observe. I'm currently trying to train myself.
I'm trying to display a "keyboard" (all letters from A to Z) and am trying to collect the data (the letter displayed) by implementing an onclick event on each letters.
However, even though my onclick event seems to be working, I'm getting an "undefined" answer in the console.
The handleLetterClicked() method is working fine but the handleKeyClicked() is not so I'm doing something wrong but can't get my head around it...
I hope you can help. thx in advance.
This is my keyboard component:
import React from 'react'
import './Keyboard.css'
const alphabet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
const displayKeyboard = alphabet.map((lettreAlphabet) =>
<div className="keyboardKey">
{lettreAlphabet}
</div>
)
const Keyboard = ({ lettreAlphabet, onClick }) => (
<div className={lettreAlphabet} onClick={() => onClick(lettreAlphabet)}>
<span className="touche">
{displayKeyboard}
{lettreAlphabet}
</span>
</div>
)
export default Keyboard
This is my app:
import React, { Component } from 'react'
import GuessCount from './GuessCount'
import Letter from './Letter'
import Keyboard from './Keyboard'
import './App.css'
class App extends Component {
handleKeyClicked(lettreAlphabet){
console.log(lettreAlphabet, 'clicked')
}
handleLetterClicked(letter){
console.log(letter, 'alsoClicked')
}
render() {
return (
<div className="container">
<div className="pendu">
<GuessCount guesses={0} />
<Letter letter="Z" feedback="visible" onClick={this.handleLetterClicked} />
</div>
<div className="keyboard">
<Keyboard onClick={this.handleKeyClicked}/>
</div>
</div>
)
}
}
export default App;
I am creating a basic blog in react using Flux + React Router + Firebase. I am having trouble trying to get a single blog post to render. When I click on the link to a single post, I try to filter out all of the other posts from a list of all posts and display only a single post from my firebase database.
I attempt to do this by matching the key of the firebase entry with the url params like so if (this.props.routeParams.key===key) . I really do not know what I have to do to make this happen. Any suggestions are welcome.
Below is Blogger.jsx, the page where I allow a user to create a blog post and then beneath the blog post, I display a list of the titles all blog posts.
import AltContainer from 'alt-container';
import React from 'react';
import { Link } from 'react-router';
import List from './List.jsx'
import Firebase from 'firebase'
import BlogStore from '../stores/BlogStore'
import BlogActions from '../actions/BlogActions';
const rootURL = 'https://incandescent-fire-6143.firebaseio.com/';
export default class Blogger extends React.Component {
constructor(props) {
super(props);
BlogStore.getState();
BlogStore.mountFirebase();
{console.log(this.props.location.query)}
};
componentDidMount() {
BlogStore.listen((state) => {
this.setState(state)
})
this.firebaseRef = new Firebase(rootURL + 'items/');
}
componentWillMount() {
BlogStore.unlisten((state) => {
this.setState(state)
})
}
renderList = (key) => {
return (
<Link to={`blogshow/${key}`}> <List key={key} blog={this.state.blog[key]} /> </Link>
)
}
handleInputChange = () => {
BlogStore.setState({
title: this.refs.title.value,
text: this.refs.text.value});
}
handleClick = () => {
BlogStore.handleClick();
}
render() {
return (
<div>
<div className="row panel panel-default">
<div className="col-md-8 col-md-offset-2">
<h2>
Create a New Blog Post
</h2>
</div>
</div>
<h2>Blog Title</h2>
<div className="input-group">
<input
ref="title"
value={BlogStore.state.title}
onChange = {this.handleInputChange}
type="text"
className="form-control"/>
<span className="input-group-btn">
</span>
</div>
<h2>Blog Entry</h2>
<div className="input-group">
<textarea
ref="text"
value={BlogStore.state.text}
onChange = {this.handleInputChange}
type="text"
className="form-control"/>
</div>
<div className="blog-submit input-group-btn">
<button onClick={this.handleClick}
className="btn btn-default" type="button">
Publish Blog Post
</button>
</div>
{/*<List blog={this.state.blog} />*/}
{Object.keys(BlogStore.state.blog)
.map(this.renderList)}
</div>
);
}
}
When a user clicks on a link to a single blog post, they should be transported to a page which shows only that single blog post. I have called this component BlogShow. I can't get BlogShow to render because I keep on getting the error
invariant.js?4599:45 Uncaught Invariant Violation: BlogShow.render(): A
valid React element (or null) must be returned. You may have returned
undefined, an array or some other invalid object.
This is BlogShow.jsx:
import AltContainer from 'alt-container';
import React from 'react';
import { Link } from 'react-router';
import Blogger from './Blogger'
import List from './List'
const rootURL = 'https://incandescent-fire-6143.firebaseio.com/';
import BlogStore from '../stores/BlogStore'
import BlogActions from '../actions/BlogActions';
export default class BlogShow extends React.Component {
constructor(props) {
super(props);
{console.log(this.props.routeParams.key)}
this.filterList = this.filterList.bind(this);
}
filterList(key) {
if (this.props.routeParams.key===key) {
return (<List key={key} blog={BlogStore.state.blog[key]} />)
}
}
render() {
<div> {Object.keys(BlogStore.state.blog).map(this.filterList)} </div>
}
}
You are getting that error because your Component BlogShow is not returning anything.
render() {
<div> {Object.keys(BlogStore.state.blog).map(this.filterList)} </div>
}
Should be:
render() {
return <div> {Object.keys(BlogStore.state.blog).map(this.filterList)} </div>
}
I'm not familiar with React.js at all, but I am familiar with pure JS arrays. To remove elements from an array, you should use .filter(), and then afterwards you can map the items.
Something like this:
filterList(key) {
return this.props.routeParams.key === key; // true if the item should stay in the list
}
mapList(key) {
return <List key={key} blog={BlogStore.state.blog[key]} />;
}
render() {
return <div> {Object.keys(BlogStore.state.blog).filter(this.filterList).map(this.mapList)} </div>;
}