I want a comment to be posted one after another but not exactly sure how to implement it. Right now, the new comment is replacing the old one. After reading some posts, I think this.props.children could be the answer but stil somewhat confused, so please let me know the best way to implement what I want to. Thanks.
Comment.js:
import React from 'react';
import { Display } from './Display';
export default class Comment extends React.Component {
constructor(props) {
super(props);
this.state = { buttonClicked: false, count: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({ buttonClicked: true , count : this.state.count + 1 });
console.log('Button clicked');
}
render() {
const comment_form =(
<div className="posts" >
<input type="text" id="comment-box" name="comment" placeholder="Say something nice." />
<button className="submit-button" type="button" onClick={this.handleClick}>Comment</button>
</div>
);
if (this.state.buttonClicked) {
return (
<div>
{comment_form}
<Display commentNumber={this.state.count} />
</div>
);
} else {
return (<div> {comment_form} </div>);
}
}
}
Display.js:
import React from 'react';
import './App.css';
export class Display extends React.Component {
constructor(props){
super(props);
}
render() {
console.log('display rendered');
const comments = (
<div className="display-comments">
<p>Comment {this.props.commentNumber} :{ document.getElementById('comment-box').value }</p>
</div>
);
return (
<div>
{comments}
</div>
);
}
}
Use the map function to dynamically render the elements.
Link: https://reactjs.org/docs/lists-and-keys.html
Related
I am building a link preview and I want to get the input from a user then display it with MicroLink, the problem that every time i want to get the link i get 'Failed to construct 'URL': Invalid URL'
import Microlink from '#microlink/react'
import React from 'react'
export default class LinkPreviewer extends React.Component {
constructor(props){
super(props)
this.state={
url:'https://www.robinwieruch.de/react-preventdefault'
}
this.handelChange = this.handelChange.bind(this)
}
handelChange(e){
console.log(e)
this.setState({
url:e.target.value
})
}
render() {
return (
<div>
<div>
<input type='text' name='url' value={this.state.url} onChange={this.handelChange}/>
</div>
<div>
</div>
<Microlink
url={this.url}
/>
</div>
);
}
}
this.url doesn't exist, it's this.state.url, so you need to replace your code by this :
<Microlink
url={this.state.url}
/>
I am writing a react application that outputs a list of books (image, title, category, and description).
My search bar and booklist are sibling components and the search bar will pass data to the booklist.
when clicking the search button, only "Sample Category" shows up but not anything else. There is no problem accessing the API and the data is not null.
Here is a sample API output: https://www.googleapis.com/books/v1/volumes?q=lordoftherings
My code is the following:
// App
import React, { Component } from 'react';
import Axios from 'axios';
import './App.css';
import SearchBar from './SearchBar';
import BookList from './BookList';
class App extends Component {
constructor(props) {
super(props);
this.state = {
books: []
};
this.search = this.search.bind(this);
}
search(title) {
const promise = Axios.get('https://www.googleapis.com/books/v1/volumes?q=' + title);
promise.then((response) => {
const books = response.data.items;
this.setState({ books: books });
console.log(this.state.books);
})
};
render() {
return (
<div className="App">
<SearchBar searchBooks = {this.search}/>
<BookList booklist = {this.state.books}/>
</div>
);
}
}
export default App;
// Search Bar
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = { titleToSearch: 'harry potter' }
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(e) {
this.setState({ titleToSearch: e.target.value });
};
render() {
return (
<form>
<input
type="text"
name="booksInput"
placeholder="Enter book title"
value={this.state.titleToSearch}
onChange={this.handleInputChange}
/>
<button type="button" onClick={() => this.props.searchBooks(this.state.titleToSearch)}>Search</button>
</form>
);
}
}
export default SearchBar;
// BookList
import React, { Component } from 'react';
class BookList extends Component {
render() {
const books = this.props.booklist;
return (
<div className="table">
{books.map((book) => {
console.log(book.id);
return (
<div className="box" key={book.id}>
<div className="img"><img src="assets/default-placeholder.jpg" alt="" /></div>
<div className="title">{book.title}</div>
<div className="category">Sample Category</div>
<div className="description">{book.description}</div>
</div>
);
})}
</div>
);
}
}
export default BookList;
In the sample code you provided, you're not actually dynamically outputting categories.
You've hard coded 'Sample category' in there.
book.category
...is not actually in the dataset.
There are categories which seem to be available under:
<div className="category">{book.volumeInfo.categories[0]}</div>
although you'll want to check if the array has length, and probably map or join each item in array to string.
just to be clear: the issue with your other fields is also that they're children of "volumeInfo"
Hello everybody I'm wondering if I can pass a state value from a component to other where I'm returning jsx code to be displayed for example I have 3 components.
1
import React, { Component } from 'react';
import Conteneur from './Conteneur';
class Header extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
<Conteneur values={this.state.value} />
</form>
);
}
}
export default Header;
2 app.js
import React, { Component } from 'react';
import Header from './Header';
import Conteneur from './Conteneur';
import './App.css';
class App extends Component {
render() {
return (
<div className="App" >
<br />
<Header />
<br />
<Conteneur />
</div>
);
}
}
export default App;
3 and finally
import React, { Component } from 'react';
const Conteneur = () => {
return (
<div className="tab"><span>ok test </span></div>
);
};
export default Conteneur;
I like to pass the state value of header that I have from the input to conteneur and then display in the box while I have some code all the examples that I saw online they are sending state like this:
class Dashboard extends Component {
...
...
render(){
return(
<Sidebar data={this.state.data1}/>
);
}
}
So can I do like this <Conteneur values={this.state.value} /> in the form ?
And I imported Conteneur.
i updated the code but the output is
Yes you can do, only one thing you are missing. Receive the props in the function parameters then render that in the ui.
Like this:
const Conteneur = (props) => {
return (
<div className="tab"><span>value: {props.value} </span></div>
);
};
I'm new to ReactJs, coding and this is my first time posting here! So, I'm trying to build a Todo app in ReactJs. I have four components.
the first compo. is App.js - the parent one
import React, { Component } from 'react';
import TaskTodo from './TaskTodo';
import './App.css';
import TaskDisplayed from "./TaskDisplayed";
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">Hey, i'm the header! </h1>
</header>
<div className="App-intro">
<TaskTodo/>
</div>
<div className="App-right">
<TaskDisplayed/>
</div>
</div>
);
}
}
export default App;
TaskTodo.js - which is the parent of the TodoItems.js
import React, {Component} from 'react';
import TodoItems from './TodoItems';
export default class TaskTodo extends Component{
constructor(props) {
super(props);
this.state = {
items: []
};
this.addItem = this.addItem.bind(this);
};
addItem(e) {
const itemArray = this.state.items;
if (this._inputElement.value !== "") {
itemArray.unshift(
{
text: this._inputElement.value,
key: Date.now()
}
);
this.setState({
items: itemArray
});
this._inputElement.value = "";
}
e.preventDefault();
}
render() {
return (
<div className="todoListMain">
<div className="header">
<form onSubmit={this.addItem}>
<input type="text" ref={(a) => this._inputElement = a}
placeholder="Add a list">
</input>
</form>
</div>
<TodoItems entries={this.state.items}/>
</div>
);
}
}
TodoItems.js - the child of the TaskTodo.js
import React, { Component } from 'react';
class TodoItems extends Component {
constructor(props) {
super(props);
this.createTasks = this.createTasks.bind(this);
}
handleClick = (text) => {
console.log(text);
}
createTasks(item) {
return <li key={item.key}><a onClick={() => this.handleClick(item.key, item.text)} href={'#about'}>#{item.text}</a></li>
}
render() {
const todoEntries = this.props.entries;
const listItems = todoEntries.map(this.createTasks);
return (
<ul className="theList">
{listItems}
</ul>
);
}
};
export default TodoItems;
What I need to do, is how I can pass the handleClick method (a child's of TaskTodo) to an 'external' component - TaskDisplayed.js; or how I can track when the user click to a listed item? Please pardon me for this unprofessional way of asking! But, I truly need to get in track with ReactJS! Thanks!
p.s. The above code I found online, so thanks for that :D!
You should define the onClick event handler in the parent component and pass it to the child as a prop.
See How to pass an event handler to a child component in React
In this case, you would want to define it in the App component since that is the parent of the two components that need to communicate.
it is necessary in the method clickSubmitComment(), write logic added to the array of comments text of the textarea, I'm still learning tell me how or share a link.
comment.jsx:
import React from 'react';
export default class Comment extends React.Component {
constructor(props){
super(props);
}
render() {
const comment = this.props.comment.map((commentForm, index) => {
return <CommentForm key={index} {...commentForm}/>
});
return (
<div className="media-body">{comment}<br></br></div>
);
}
}
and, commentForm.jsx:
import React from 'react';
export default class CommentForm extends React.Component {
constructor(props){
super(props);
this.clickSubmitComment = this.clickSubmitComment.bind(this);
this.comments = [];
}
clickSubmitComment() {
textarea -> comments -> send props to comment.jsx and view?
}
render() {
return (
<div><textarea className="form-control" rows="3"></textarea><br></br>
<button type="submit" className="btn btn-primary" onClick={this.clickSubmitComment}>Submit</button></div>
);
}
}
import React from 'react';
export default class Comment extends React.Component {
constructor(props){
super(props);
}
handleCommentChange(text){
// do something with the text
}
render() {
const comment = this.props.comment.map((commentForm, index) => {
return <CommentForm key={index} {...commentForm} handleCommentChange = {this.handleCommentChange.bind(this)}/>
});
return (
<div className="media-body">{comment}<br></br></div>
);
}
}
import React from 'react';
export default class CommentForm extends React.Component {
constructor(props){
super(props);
this.state = {
text: ''
};
this.updateState = this.updateState.bind(this);
}
updateState(e){
this.setState({text: e.target.value});
}
render() {
return (
<div><textarea value={this.state.text} className="form-control" onChange={this.updateState()} rows="3"></textarea><br></br>
<button type="submit" className="btn btn-primary" onClick={this.props.handleCommentChange(this.state.text)}>Submit</button></div>
);
}
}
Add onChange to your textarea and save its value to the state, and then onButton click get the state value. Something like this :
class Test extends React.Component {
constructor(props){
super(props);
this.state = {
comment: ""
}
}
handleComment(e){
this.setState({comment: e.target.value});
}
clickSubmitComment(){
let comment = this.state.comment;
//Do what you will with the comment
}
render(){
return (
<div>
<div><textarea className="form-control" rows="3" onChange={this.handleComment.bind(this)}>{this.state.comment}</textarea><br></br>
<button type="submit" className="btn btn-primary" onClick={this.clickSubmitComment.bind(this)}>Submit</button></div>
</div>
)
}
}
React.render(<Test />, document.getElementById('container'));
Here is a fiddle.