Not able to add email field in react web app - reactjs

I am developing a small React App that is integrating with Mobx. I have setup a members store which is the following:
import {observable, action, computed} from 'mobx';
class MemberStore {
#observable members = [];
#action addMember(data) {
const existing = this.members;
this.members = existing.concat(data);
}
#computed get memberCount() {
return this.members.length;
}
}
const store = new MemberStore();
export default store;
Now I have a contact page which has a form of Name and email. Now I am able to add a name but not the email. So basically when I click the submit button I only get the name and a 0 next to the name.
import React, { Component } from 'react';
import Navbar from '../components/Navbar';
import Footer from '../components/Footer';
import Jumbotron from '../components/Jumbotron';
import {inject, observer} from 'mobx-react';
#inject('MemberStore')
#observer
class Contact extends Component {
handleSubmit = (e) => {
e.preventDefault();
const member = this.member.value;
const email = this.email.value;
// const email = this.email.value;
this.props.MemberStore.addMember(member, email);
this.member.value = '';
this.email.value = '';
}
render() {
const {MemberStore} = this.props;
return (
<div>
<Navbar />
<Jumbotron title="Contact Page" subtitle="You want to get in touch"/>
<div className="container">
<h2>You have {MemberStore.memberCount} members.</h2>
<form onSubmit={e => this.handleSubmit(e)}>
<input type="text" placeholder="Enter Your Name" ref={input => this.member = input }/>
<div>
<input type="text" placeholder= "Enter Your Email" ref={input => this.email = input }/>
</div>
<button>Submit</button>
</form>
<ul>
{MemberStore.members.map((member,email) => (
<li key={member}>
{member}
{email}
</li>
))}
</ul>
</div>
<Footer />
</div>
)
}
}
export default Contact;
Any help would be appreciated.

Your problem is probably that addMember takes one parameter data, and you’re passing two parameters to it when you call it: addMember(name, email).
You should pass the name and email in as an object instead:
addMember({name, email})
Your code that maps the MemberStore.members array to JSX is also taking two parameters, when it should only take one object as a param:
{MemberStore.members.map({member,email}) => (
Note that I’m using the ES6 Object Literal Property Value Shorthand syntax above.

Related

Output data from an input field as list elements in React fails - why?

I am trying to output data from an input field as list elements. However, I always get the error message "addData is not a function" just before the finish line. Does anyone happen to have an idea where my error is? I have the feeling that the majority should be correct.
Thanks to all of you!
Heres my App.js
import "./styles.css";
import Form from "/src/Form";
import { React, useState } from "react";
export default function App() {
const [displayData, setDisplayData] = useState([]);
const addData = (formData) => {
setDisplayData([...displayData, { formData: formData }]);
};
return (
<div className="App">
<ul>
{displayData.map((data) => (
<li data={data.formData} />
))}
</ul>
<Form formData={addData} />
</div>
);
}
And this is my Form.js
import { React, useState } from "react";
const Form = ({ addData }) => {
const [formData, setFormData] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
addData(formData);
};
return (
<div>
<form onSubmit={handleSubmit}>
<label>Hier kommt die neue Form:</label>
<br />
<input
placeholder="Vor- und Nachname"
type="text"
value={formData}
required
onChange={(event) => setFormData(event.target.value)}
></input>
<br />
<input placeholder="Hausnummer und PLZ" type="text" required></input>
<br />
<button>Submit</button>
</form>
</div>
);
};
export default Form;
The prop you're passing is called formData:
<Form formData={addData} />
But the component is expecting it as addData:
const Form = ({ addData }) => {
Change one to match the other. Since the component already has a state variable called formData, it's probably easier to change the usage:
<Form addData={addData} />

How do I transfer the value of the inputs from one page to another?

On one page I have two inputs and a button, after clicking on the button goes to the second page, how do I get data from the inputs on the second page?
navigate(path, { state: { input_value: value }}) ?
index.js
import './App.css';
function App() {
return (
<div className='App'>
<header className='App-header'>
<input type='text' placeholder='Name'/>
<input type='text' placeholder='Surname'/>
<button type='submit'>Send</button>
</header>
</div>
);
}
export default App;
getData.js
export const getData = () => {
return (
<div>
<h1>Name:</h1>
<h1>Surname:</h1>
</div>
)
};
You can have a state variable in the App component and then pass the state as a prop to GetData:
import './App.css';
import { useState, useRef } from "react";
function App() {
const nameInput = useRef(null);
const surNameInput = useRef(null);
const [fullName, setFullName] = useState({
name: "",
surName: ""
});
const sendData = () => {
// you can do some input validation here
setFullName({
name: nameInput.current.value,
surName: surNameInput.current.value,
});
}
return (
<div className='App'>
<header className='App-header'>
<input type='text' placeholder='Name'
ref={nameInput}
/>
<input type='text' placeholder='Surname'
ref={surNameInput}
/>
<button onClick={sendData}>Send</button>
</header>
<!-- some more markup here -->
</div>
);
}
export default App;
Here's how you pass your data to GetData component:
<GetData fullName={fullName} />
And then in your GetData component you get the passed props and display them:
export const GetData = (fullName) => {
return (
<div>
<h1>Name: {fullName.name}</h1>
<h1>Surname: {fullName.surName}</h1>
</div>
)
};
You can read more about hooks like useState and useRef here
So this might be Part 1 of an answer.
Taking the code you have, I've put the fields in form tag, then called handleSubmit from the built in onSubmit that is called when you click a button of type='submit' inside a form.
The values is taken from the event parameter (e) of the onSubmit (you can identify these by the 'name' attribute on the input tags) and then I am using useState hook to store the two values.
This would be where part one ends. You have the data, and you can see how it is passed to the GetDate component (the deconstructed props {name, surname} that are passed in.
From there, you should follow the documentation for your chosen router and, if you run into trouble, post the code you've tried and I can continue to help.
https://v5.reactrouter.com/web/guides/quick-start
import React, { useState } from 'react';
import { GetData } from './GetData';
export function App() {
const [theName, setTheName] = useState('');
const [theSurname, setTheSurname] = useState('');
const handleSubmit = (e) => {
setTheName(e.target.name.value);
setTheSurname(e.target.surname.value);
e.preventDefault();
}
return (
<div className='App'>
<header className='App-header'>
<form onSubmit={handleSubmit}>
<input type='text' placeholder='Name' name='name'/>
<input type='text' placeholder='Surname' name='surname'/>
<button type='submit'>Send</button>
</form>
</header>
<GetData name={theName} surname={theSurname} />
</div>
);
}
export default App;
Here is a component like your getData function.
I've added it to the App component, just so you can see the values being displayed, but for what you are looking for, you will need to read the documentation for react-router-dom
import React from "react";
export const GetData = ({name, surname}) => {
return (
<div>
<h1>Name:{name}</h1>
<h1>Surname:{surname}</h1>
</div>
)
};

TypeError: Cannot destructure property 'name' of 'props.todo' as it is undefined. React

I am creating To do list app in React. It reads the input field correctly from state, but, when I added file, which reads all the information from input and outputs it as a new div with the name of todo item, it shows an error - "TypeError: Cannot destructure property 'name' of 'props.todo' as it is undefined".
import React, {useState} from 'react';
import './App.css';
import {Container, Row, Col} from 'react-bootstrap';
import AddForm from './components/AddForm';
import TodoList from './components/TodoList';
function App() {
const [todos, addTodos] = useState([]);
const addTodoHandler = todo => addTodos([...todos, todo]);
return (
<Container fluid>
<Row>
<h1>Todo list</h1>
<Col>
<TodoList todos={todos} />
</Col>
<Col>
<AddForm addTodoHandler={addTodoHandler}/>
</Col>
</Row>
</Container>
);
}
export default App;
import React from 'react';
const TodoList = (props) => {
const {name} = props.todo;
return (
<div>
<div>{name} </div>
<button>Delete</button>
</div>
);
}
export default TodoList;
import React from "react";
import { Button } from "react-bootstrap";
class AddForm extends React.Component {
state = {
name: "",
};
add = (e) => {
e.preventDefault();
if (this.state.name === "") {
alert("Todo cannot be empty");
return;
}
this.props.addTodoHandler(this.state);
alert(this.state.name)
this.setState({ name: "" });
};
render(){
return (
<div>
<h2>Add Todo</h2>
<form onSubmit={this.add}>
<input
type="text"
name="todo"
value={this.state.name}
onChange={(e) => this.setState({ name: e.target.value })}
/>
<Button type="submit">Add</Button>
</form>
</div>
);
}
};
export default AddForm;
As pointed out in comments you need to fix the destructuring statement to use the correct prop (todos instead of todo).
But you have an additional problem in that your <TodoList> component is not set up to render a list. You're passing todos as an array prop to <TodoList> but in <TodoList> you're using it as a single object. You'll need to fix that as well. If you want a list to be rendered you'll need to iterate over it. Something like this:
import React from 'react';
const TodoList = (props) => {
const list = props.todos || [];
return list.map(item =>
<div>
<div>{item.name} </div>
<button>Delete</button>
</div>
);
}
export default TodoList;
Note that this also checks for props.todos to be undefined and if so assigns list to be an empty array so that the render has a value and does not crash.

How to dynamically show a list of data by React?

I am new to React and trying to display list of data with checkbox and inputbox. In details, I want to grab a series of data from database and put each record into a <div> like element with checkbox and inputbox. So I can check the record and change the data and then do the re-save action after clicking a button. Since the number of data will keep changing, how to make it dynamic? Also, how can I mark down which records are being checked and need to be saved? Thanks!
Code:
App.js:
import React from 'react';
import { useState, useEffect } from 'react';
import { Menu, Message, Button, Segment } from 'semantic-ui-react';
import SemanticDatepicker from 'react-semantic-ui-datepickers';
import 'react-semantic-ui-datepickers/dist/react-semantic-ui-datepickers.css';
import Form from './Form';
export default function App(props){
const [currentDate, setNewDate] = useState(null);
const onChange = (event, data) => setNewDate(data.value);
const loadData= (event) => {
return (<Form date = {currentDate} />);
};
return (
<div className="App">
<div>
<Menu borderless>
<Menu.Item >
<div >
<img src={logo} alt="image" />
</div>
</Menu.Item>
</Menu>
<Segment>
<SemanticDatepicker onChange={onChange} />
<Button onClick={loadData}>Load Data</Button>
</Segment>
<Segment>>
</Segment>
//Here will diaplyed returned list of data after click button
</div>
</div>
)
};
Simple JSON response:
{
"APPLE":{
"PRICE":100
},
"ORANGE":{
"PRICE":20
},
"PEAR":{
"PRICE":10
}
}
You could use your data to build your form.
You need to build the state from your data.
Also, map your input fields with respect to your state.
If the state needs different input fields, you could define your input fields in deriveStateFromData.
You can check the example here
For Object.keys, you could check the docs here
import React from 'react';
const price = {
"APPLE":{
"PRICE":100
},
"ORANGE":{
"PRICE":20
},
"PEAR":{
"PRICE":10
}
}
function deriveStateFromData(data) {
let state = {}
Object.keys(data).forEach(key => {
state[key] = data[key]['PRICE']
})
return state;
}
function MyForm({ data }) {
const [form, setFormData] = React.useState(deriveStateFromData(data));
const handleChange = e => {
setFormData({ ...form, [e.target.name]: Number(e.target.value) });
}
console.log(form)
return (
<>
{Object.keys(form).map(key => {
return (
<div>
<label>{key}</label>
<input
name={key}
value={form[key]}
onChange={handleChange}
/>
</div>
)
})}
</>
)
}
const App = () => <MyForm data={price} />
export default App;

How to toggle attributes of elements created on child components that were generated after a form submission

I have the following code where someone can add names into a an array of objects. I can't get to toggle one of the elements created after submission.
import React, { Component } from 'react';
import User from './User';
class App extends Component {
constructor(props){
super(props);
this.state = {
list:list,
searchTerm:'',
userInputValue:'',
users:[],
};
}
userUpdateMethod = e =>
this.setState({
userInputValue:e.target.value
});
newUserSubmitHandler = (e) =>{
e.preventDefault();
this.setState({
users: this.state.users.concat([{name:this.state.userInputValue,isConfirmed:false}]),
userInputValue:""
});
}
toggleAttendance = () =>{
const toggleConfirmed = this.state.users.isConfirmed;
this.setState({
users:!toggleConfirmed
});
}
render() {
const {searchTerm, list} =this.state;
return (
<div className="App">
<User
a = {this.state.userInputValue}
b = {this.userUpdateMethod}
c = {this.newUserSubmitHandler}
d = {this.state.users}
e = {this.toggleAttendance}
/>
</div>
);
}
}
export default App;
The function that I can get to work is toggleAttendance and it resides on the User component
import React, { Component } from 'react';
const User = props =>
<div>
<h2>User Component</h2>
<form onSubmit={props.c}>
<input type="text" onChange={props.b} value = {props.a}/>
<button type="submit" name="submit" value="submit"> Submit</button>
</form>
<div>The follwowing will be attending:{props.d.map((user,index) =>
<div> {user.name} is {user.isConfirmed? "coming":"not coming"}
<button onClick={()=>props.e(index)}>toggle attendance</button>
</div>
)}
</div>
</div>;
export default User;
I have tried several ways to update the toggleAttendance method from the main App component but with no luck

Resources