I am trying to pass data from one component to another. but it has no parent child relation and it is independent from each other. I want to do it using flux not redux. Can anyone help me to do this? below are my code.
export class EmpSearch extends React.Component {
constructor(props) {
super(props);
this.state = {
Empnumber: ''
};
}
updateEmpNumber(e) {
this.setState({Empnumber: e.target.value});
}
render() {
return (
<div className="row">
<form>
<div className="form-group">
<label htmlFor="Empnumber">Emp Number</label>
<input type="text" className="form-control" id="Empnumber" placeholder="Emp Number" value={this.state.Empnumber} onChange={this.updateEmpNumber.bind(this)}/>
</div>
</form>
</div>
);
}
}
export default EmpSearch
The other file is where i want to send the EmpNumber is below,
class EmpDetail extends React.Component {
render() {
return (
<div className="container">
<input type="text"/>
</div>
);
}
}
export default EmpDetail;
Assuming you have already implemented the flux architecture in your app.
your 1st component will be like this.
import React from 'react';
import UserAction from '../../Actions/UserActions';
export class EmpSearch extends React.Component {
constructor(props) {
super(props);
this.state = {
Empnumber: ''
};
}
updateEmpNumber(e) {
this.setState({Empnumber: e.target.value});
UserAction.employeeNumb(this.state.Empnumber);
}
render() {
return (
<div className="row">
<form>
<div className="form-group">
<label htmlFor="Empnumber">Emp Number</label>
<input type="text" className="form-control" id="Empnumber" placeholder="Emp Number" value={this.state.Empnumber} onChange={this.updateEmpNumber.bind(this)}/>
</div>
</form>
</div>
);
}
}
export default EmpSearch
The Actions file will look like
import {dispatch,register} from '../Dispatcher/Dispatcher';
export default {
employeeNumb(Data){
dispatch({ actionType:'EMPNO',data:Data});
}
}
The Store will look like
import {dispatch,register} from '../Dispatcher/Dispatcher';
import AppConstants from '../Constants/AppConstants';
import {EventEmitter} from 'events';
const CHANGE_EVENT = 'change';
var a=0;
const UserStore = Object.assign(EventEmitter.prototype,{
emitChange(){
this.emit(CHANGE_EVENT)
},
addChangeListener(callback){
this.on(CHANGE_EVENT,callback);
},
removeChangeListener(callback){
this.removeListener(CHANGE_EVENT,callback)
},
setEmpData(data){
a=data;
},
getEmpData(){
return a;
}
});
dispatcherIndex:register((action)=>{
switch (action.actionType) {
case AppConstants.EMPNO:
UserStore.setEmpData(action.data);
UserStore.emitChange();
break;
}
UserStore.emitChange();
});
export default UserStore;
The dispatcher file
import {Dispatcher} from 'flux';
const flux = new Dispatcher();
export function register(callback){
return flux.register(callback);
}
export function dispatch(actionType,action){
flux.dispatch(actionType,action);
}
and the 2nd Component file looks like
import React from 'react';
import Store from '../../Store/UserStore';
class EmpDetail extends React.Component {
constructor(props){
super(props);
this.state={
empno:''
};
}
componentDidMount(){
Store.addChangeListener(this._onChange);
}
componentWillUnmount = () =>{
Store.removeChangeListener(this._onChange);
}
_onChange = () =>{
this.setState({empno:Store.getEmpData()});
}
render() {
return (
<div className="container">
<input type="text"/>
<input type="button" onClick={()=>{console.log(this.state.empno);}}/>
</div>
);
}
}
export default EmpDetail;
What you have tried might be slightly different but this is the normal flow for what you are looking for.
Related
I basically making a todolist app.I just want the user entered text and add it to my state.But when i click the button the state is not getting updated with the new todoItem.please help with this.
My state is in Context.js
import React from 'react';
const Context=React.createContext();
const reducer=(state,action)=>{
switch(action.type){
case "ADD_TODO":
return {
...state,
todos:[action.payload,...state.todos]
}
default:
return state;
}
}
export class Provider extends React.Component{
state={
todos:[
{id:"1",todoItem:"Code daily"},
{id:"2",todoItem:"play"},
{id: '16a1c935-a033-4272-85b4-4412de42b59f', todoItem: 'wdwdwd'},
],
dispatch:action=>{
this.setState(state=>{
reducer(state,action)
})
}
}
render(){
return(
<Context.Provider value={this.state}>
{this.props.children}
</Context.Provider>
)
}
}
export const Consumer=Context.Consumer;
My Input Component for taking the todoitem input from user and add it to the state.But my page is reloading but my user entered text is not added to the state.And there is no error showing.
InputTodo.js
import React, { Component } from 'react';
import '../css/InputTodo.css';
import { v4 as uuidv4 } from 'uuid';
import {Consumer} from '../context';
class InputTodo extends Component {
constructor(props){
super(props);
this.state={
inputValue:""
};
}
OnChange(event){
const txtEntered=event.target.value;
this.setState({
inputValue:txtEntered,
});
}
handleButtonClicked=(dispatch,event)=> {
event.preventDefault();
const inputValue=this.state.inputValue;
const newTodo={
id:uuidv4(),
todoItem:inputValue,
}
dispatch({type:'ADD_TODO',payload:newTodo});
this.setState({
inputValue:"",
});
this.props.history.push('/');
}
render() {
return(
<Consumer>
{value=>{
const {dispatch}=value;
return (
<form onSubmit={this.handleButtonClicked.bind(this,dispatch)}>
<div className="form-group">
<input value={this.state.inputValue} onChange={this.OnChange.bind(this)} className="form-control" placeholder="Enter the todo" />
<button type="submit" className="btn btn-primary">Add</button>
</div>
</form>
)}}
</Consumer>
)
}
}
export default InputTodo;
You just forgot to return the new state in dispatch setState:
export class Provider extends React.Component{
state={
/* ... */
dispatch:action=>{
this.setState(state=>{
return reducer(state,action) /* <--- Here you missed the return */
})
}
}
/* ... */
Im trying to simply create a search and results feature for an app. The value of the input should reflect the components listed in the CardList Array. The filter doesn't seem to update the CardList. I've logged steps along the way and I've come to the conclusion that its the filter I set up. I cant seem to figure out why it wont filter the list.
import React, {Component} from 'react';
import CardList from './CardList';
import {robots} from './robots';
import './index.css';
class App extends Component {
constructor() {
super()
this.state = {
robots: robots,
searchfield: ''
}
}
onSearchChange = (event) => {
this.setState({ searchfield: event.target.value });
}
render() {
const filteredRobots = this.state.robots.filter(robot => {
return robot.name.toLowerCase().includes(this.state.searchfield.toLowerCase());
});
return (
<div className="appAlign">
<h1 className="appTitle">RoboFriends</h1>
<input
className="searchBox"
type="search"
placeholder="Search Robots"
onChange={this.onSearchChange}
/>
<CardList robots={filteredRobots} />
</div>
);
}
}
export default App;
The error is not caused by the filter function as I have tested it and it works. It most probably lies with the robots data-set. I have slightly modified the filter function here.
import React, { Component } from "react";
import CardList from "./CardList";
import { robots } from "./robots";
class App extends Component {
constructor() {
super();
this.state = {
robots: robots,
searchfield: ""
};
}
onSearchChange = event => {
this.setState({ searchfield: event.target.value });
};
render() {
const filteredRobots = this.state.robots.filter(robot =>
robot.name.toLowerCase().includes(this.state.searchfield.toLowerCase())
);
return (
<div className="appAlign">
<h1 className="appTitle">RoboFriends</h1>
<input
className="searchBox"
type="search"
placeholder="Search Robots"
onChange={this.onSearchChange}
/>
<CardList robots={filteredRobots} />
</div>
);
}
}
export default App;
I have made a sandbox with your code which has a sample robots data and a Card that renders the filtered data-set. Take a look.
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>
);
};
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.