I'm doing a project to manage patient appointments and everything was fine until I installed the 'uuid' library, the library didn't give me a problem, but from then on it gave me this error, apparently it is with the useState but not I find it, I thank you in advance!
error image...
enter image description here
import React, { Fragment, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
const Form = () => {
//creando el State para las citas
const [ cita, actualizarCita ] = useState({
mascota: '',
propietario: '',
fecha: '',
hora: '',
sintomas: ''
});
const [ error, actualizarError ] = useState(false)
// funcion que se ejecutara cada vez que el usuario escribe en el input para validar lo que hace
const actualizarState = e => {
actualizarCita({
...cita,
[e.target.name]: e.target.value
})
}
// Extraer los valores de cita
const { mascota, propietario, fecha, hora, sintomas } = cita;
// Cuando el usuario envia el formulario
const submitCita = e => {
e.preventDefault();
// Validacion
if(mascota.trim() === '' || propietario.trim() === '' || fecha.trim() === '' || hora.trim() === '' || sintomas.trim() === ''){
actualizarError(true);
return;
}
}
// Eliminando el mensaje previo
actualizarError(false);
// Asignando un ID
cita.id = uuidv4();
return (
<Fragment>
<h2> Crear Cita </h2>
{ error ? <p className="alerta-error">Todos los campos son obligatorios</p> : null }
<form
onSubmit={submitCita}
>
<label>Nombre Mascota</label>
<input
type="text"
name="mascota"
className="u-full-width"
placeholder="Nombre Mascota"
onChange={actualizarState}
value={mascota}
/>
<label>Nombre Dueño </label>
<input
type="text"
name="propietario"
className="u-full-width"
placeholder="Nombre dueño de la mascota"
onChange={actualizarState}
value={propietario}
/>
<label>Fecha </label>
<input
type="date"
name="fecha"
className="u-full-width"
onChange={actualizarState}
value={fecha}
/>
<label>Hora </label>
<input
type="time"
name="hora"
className="u-full-width"
placeholder="Nombre dueño de la mascota"
onChange={actualizarState}
value={hora}
/>
<label>Sintomas</label>
<textarea
className="u-full-width"
name="sintomas"
onChange={actualizarState}
value={sintomas}
></textarea>
<button
type="submit"
className="u-full-width button-primary"
>Agregar Cita</button>
</form>
</Fragment>
)
}
export default Form;
you can't update state out side function,
actualizarError(false);
you should remove this, otherwise infinite re-render
It's hard to be sure what the problem might be without a proper sandbox (codesandbox for example).
But the error seems to indicate that you've gotten stuck in an infinite loop, which usually means the component is cause its own state dependencies to change, which causes a redraw (which again causes a change, etc.)
I'd start by moving
// Eliminando el mensaje previo
actualizarError(false);
into
const actualizarState = e => {
actualizarCita({
...cita,
[e.target.name]: e.target.value
})
}
Related
I am in a very complicated situation. I have a React component which is a drag and drop that takes an excel file. I am required to validate some columns from the Excel file. This part I already managed to solve using the validateFile function inside the component. This function compares an array of strings (the columns to validate) to the actual columns inside the Excel file. The part that I don't know how to do is to render the validated columns to a div or something, instead of the Card component which is the drag and drop box. I will share the code and hopefully someone can help me with this. Thanks in advance.
// #ts-nocheck
// ** React Imports
import { useState, Fragment } from "react";
// ** Reactstrap Imports
import {
Card,
CardHeader,
CardTitle,
CardBody,
Button,
ListGroup,
ListGroupItem,
Toast,
ToastBody,
ToastHeader,
Spinner,
Row,
Col,
} from "reactstrap";
import "../../../styles/lots-modals.scss";
// ** Third Party Imports
import { useDropzone } from "react-dropzone";
import toast from "react-hot-toast";
import { FileText, X, DownloadCloud } from "react-feather";
const XLSX = require("xlsx");
//Extra components
import ExcelValidationTable from "./ExcelValidationTable";
const FileUploaderSingle = () => {
// ** State
const [files, setFiles] = useState([]);
const [open, setOpen] = useState(true);
const [showTable, setShowTable] = useState(false);
const closeModal = () => {
setOpen(false);
};
const { getRootProps, getInputProps } = useDropzone({
multiple: false,
onDrop: (acceptedFiles) => {
const xlsFiles = acceptedFiles.filter(
(file) => file.name.endsWith(".xls") || file.name.endsWith(".xlsx")
);
if (xlsFiles.length === 0) {
toast.error(
() => (
<p className="mb-0">
Solo puede subir archivos de tipo{" "}
<span className="fw-bolder">.xls</span> &{" "}
<span className="fw-bolder">.xlsx</span>{" "}
</p>
),
{
style: {
minWidth: "280px",
},
}
);
return;
}
setFiles([...files, ...xlsFiles.map((file) => Object.assign(file))]);
},
});
const renderFilePreview = (file) => {
if (file.type.startsWith("image")) {
return (
<img
className="rounded"
alt={file.name}
src={URL.createObjectURL(file)}
height="28"
width="28"
/>
);
} else {
return <FileText size="28" />;
}
};
const handleRemoveFile = (file) => {
const uploadedFiles = files;
const filtered = uploadedFiles.filter((i) => i.name !== file.name);
setFiles([...filtered]);
};
const renderFileSize = (size) => {
if (Math.round(size / 100) / 10 > 1000) {
return `${(Math.round(size / 100) / 10000).toFixed(1)} mb`;
} else {
return `${(Math.round(size / 100) / 10).toFixed(1)} kb`;
}
};
const fileList = files.map((file, index) => (
<ListGroupItem
key={`${file.name}-${index}`}
className="d-flex align-items-center justify-content-between"
>
<div className="file-details d-flex align-items-center">
<div className="file-preview me-1">{renderFilePreview(file)}</div>
<div>
<p className="file-name mb-0">{file.name}</p>
<p className="file-size mb-0">{renderFileSize(file.size)}</p>
</div>
</div>
<Button
color="danger"
outline
size="sm"
className="btn-icon"
onClick={() => handleRemoveFile(file)}
>
<X size={14} />
</Button>
</ListGroupItem>
));
const handleRemoveAllFiles = () => {
setFiles([]);
};
// Function to validate the Excel file for sheets and columns.
const validateFile = async (files) => {
const file = files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function (e) {
const buffer = new Uint8Array(e.target.result).buffer;
const workbook = XLSX.read(buffer, { type: "buffer" });
const sheetNames = workbook.SheetNames;
if (sheetNames.includes("PLANILLAS") && sheetNames.length === 1) {
const sheet = workbook.Sheets["PLANILLAS"];
const headerRow = XLSX.utils.sheet_to_row_object_array(sheet, {
header: 1,
})[0];
const headerValues = Object.values(headerRow).map((value) =>
value
.toUpperCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
);
// console.log(headerValues);
const requiredColumns = [
"PRIMER NOMBRE",
"SEGUNDO NOMBRE",
"TERCER NOMBRE",
"PRIMER APELLIDO",
"SEGUNDO APELLIDO",
"APELLIDO DE CASADA",
"FECHA DE NACIMI. DD/MM/AAAA",
"NACIONALIDAD",
"PAIS NACIMIENTO",
"DEPARTAMENTO NACIMIENTO",
"MUNICIPIO NACIMIENTO",
"GENERO (MARGINAR ENTRE F/M)",
"ESTADO FAMILIAR",
"RESIDENTE",
"SUJETO IMPUESTO SOBRE LA RENTA-(EXTRANJEROS)",
"DUI A 9 DIGITOS SIN GUIONES",
"FECHA DE EXPEDICION DEL DUI (DD-MM-ANO)",
"FECHA DE VENCIMIENTO DEL DUI (DD-MM-ANO)",
"PAIS EXPEDICION DUI",
"DEPARTAMENTO EXPEDICION DUI",
"CIUDAD DE EXPEDICION DUI",
"NUMERO DE NIT (HOMOLOGACION 9 DIGITOS, SIN HOMOL. 14 DIGITOS",
"FECHA DE EXPEDICION DEL NIT DD/MM/AAAA",
"PASAPORTE",
"CARNE DE RESIDENTE (8 DIGITOS SIN GUIONES)",
"CALIDAD MIGRATORIA",
"DIRECCION PRINCIPAL(DOMICILIO)",
"PAIS DOMICILIO",
"DEPARTAMENTO DOMICILIO",
"MUNICIPIO DOMICILIO",
"NUMERO DE TELEFONO CELULAR (8 DIGITOS SIN GUIONES)",
"NUMERO DE TELEFONO FIJO (8 DIGITOS SIN GUIONES)",
"CORREO ELECTRONICO PERSONAL",
"ORIGEN DE INGRESOS",
"TIEMPO DE LABORAR EN LA EMPRESA ANOS",
"TIEMPO DE LABORAR EN LA EMPRESA MESES",
"PROFESION",
"OCUPACION U OFICIO",
"EMPRESA",
"PUESTO",
"DIRECCION DE LA EMPRESA",
"PAIS EMPRESA",
"DEPTO EMPRESA",
"MUNI EMPRESA",
"TELEFONO FIJO OFICINA - SIN GUIONES",
"TELEFONO CONTACTO - SIN GUIONES",
"SUELDO MENSUAL",
"PAIS ACTIVIDAD ECONOMICA",
"DEPARTAMENTO ACTIVIDAD ECONOMICA",
"MUNICIPIO ACTIVIDAD ECONOMICA",
];
if (headerValues.every((value) => requiredColumns.includes(value))) {
toast.success(
() => (
<p className="mb-0">
<strong>Carga exitosa!</strong>
</p>
),
{
style: {
minWidth: "280px",
margin: "0 auto",
},
}
);
return true;
} else {
toast.error(
() => (
<p className="mb-0">
<strong>Faltan columnas requeridas.</strong>
</p>
),
{
style: {
minWidth: "280px",
margin: "0 auto",
},
}
);
return false;
}
} else if (sheetNames.includes("PLANILLAS")) {
toast.error(
() => (
<p className="mb-0">
Se detectaron otras hojas en el archivo. Solo debe contener la
hoja
<strong> PLANILLAS.</strong>
</p>
),
{
style: {
minWidth: "280px",
margin: "0 auto",
},
}
);
return false;
} else {
toast.error(
() => (
<p className="mb-0">
No se encontró la hoja
<strong> PLANILLAS </strong>
en el archivo.
</p>
),
{
style: {
minWidth: "280px",
margin: "0 auto",
},
}
);
return false;
}
};
};
return (
<>
{open && !showTable && (
<Card>
<CardHeader></CardHeader>
<CardBody>
<div {...getRootProps({ className: "dropzone" })}>
<input {...getInputProps()} />
<div className="d-flex align-items-center justify-content-center flex-column">
<DownloadCloud size={64} />
<h5>Arrastre el archivo aquí o haga click para cargar</h5>
<p className="drag-drop-text-secondary">
Arrastre archivos aquí o haga click en{" "}
<a href="/" onClick={(e) => e.preventDefault()}>
buscar
</a>{" "}
para importar el archivo.
</p>
</div>
</div>
{files.length ? (
<Fragment>
<ListGroup className="my-2">{fileList}</ListGroup>
<div className="d-flex justify-content-end">
<Button
className="me-1"
color="danger"
outline
onClick={handleRemoveAllFiles}
>
Eliminar Archivo
</Button>
<Button
color="primary"
onClick={() => {
validateFile(files);
setShowTable(true);
}}
>
Cargar Archivo
</Button>
</div>
</Fragment>
) : null}
</CardBody>
</Card>
)}
{showTable && <ExcelValidationTable />}
</>
);
};
export default FileUploaderSingle;
I tried asking chatgpt but nothing works. I am just a junior and landed on this project that is too much for me. I am trying to complete this task and I will let them know that this is not for me.
I have this fetch where I'm trying to post a form in MongoDB.
When I fill the form I get this back:
SyntaxError: Unexpected end of input at ContactRequest.js:3:1
And I don't know why, because the fetch receives the data from the form and testing the endpoint in postman it works perfectly.
The fetch should works because I used the same Fetch in other projects.
This is the fetch component.
const contactRequest = (params) => {
console.log(`Test ${JSON.stringify(params)}`);
fetch(`http://localhost:4000/contact`, {
method: "POST",
body: JSON.stringify(params),
mode: "no-cors",
headers: {
'Content-Type': 'application/json'
}})
.then(res => res.json())
.catch((e) => console.error(e));
};
export default contactRequest;
This is the form component:
import React, {useState} from 'react';
import contactRequest from '../Request/ContactRequest';
import './Contact.css';
const initialState = {
nameAndSurname: "",
email: "",
phoneNumber: "",
message: "",
};
const Contact = () => {
const [contactData, setContactData] = useState(initialState);
const handlerInput = (e) => {
setContactData({
...contactData,
[e.target.name] : e.target.value
});
};
const handlerSubmit = (e) => {
e.preventDefault();
setContactData(initialState);
contactRequest(contactData);
alert("Hemos recibido tu mensaje.");
}
return (
<div>
<form onSubmit={handlerSubmit}>
<label className="nameAndSurname-label">
Nombre y Apellido: <br/>
<input
id="nameAndSurname"
type="text"
name="nameAndSurname"
placeholder="Ingrese su nombre y apellido"
onChange={handlerInput}
value={contactData.nameAndSurname}
required/> <br/>
</label>
<div className="email-phoneNumber-div">
<label>
Email: <br/>
<input
id="email"
type="email"
name="email"
placeholder="Ingrese su email"
onChange={handlerInput}
value={contactData.email}
required/> <br/>
</label>
<label>
Numero de teléfono: <br/>
<input
id="phoneNumber"
type="number"
name="phoneNumber"
placeholder="Ingrese su numero de teléfono"
onChange={handlerInput}
value={contactData.phoneNumber}
required/> <br/>
</label>
</div>
<label>
Mensaje: <br/>
<input
id="message"
type="text"
name="message"
placeholder="Ingrese su mensaje"
onChange={handlerInput}
value={contactData.message}
required/> <br/>
</label>
<label>
Al enviar este formulario, acepto los terminos y condiciones.
</label>
<button
id="submit-btn"
type="submit"
value="Submit">Enviar</button>
</form>
</div>
</div>
)
}
export default Contact;
This is the Endpoint.
const express = require('express');
const router = express.Router();
const Contact = require('../models/Contact.js');
router.post('/contact', (req, res) => {
console.log(req.body);
console.log(req.text);
let contact = new Contact()
contact.nameAndSurname = req.body.nameAndSurname
contact.email = req.body.email
contact.phoneNumber = req.body.phoneNumber
contact.message = req.body.message
contact.save((err, contactStored) => {
if(err) {
res.status(500).send({message: `Error ${err}`})
}else {
res.status(200).send({contact: contactStored})
}
})
})
module.exports = router;
Why are you using mode: "no-cors"? This results in an "opaque" response, without body, so without anything to convert to json
I am using Formik in my react project, I have implemented all the validations with yup and succesfully showing the errors. One thing i want is if user clicks on submit button i want to scroll it to the section which has validation errors in it.
I tried a way but couldnt achieve it here is the code below
but it gives me error
document.getElementsByName(Object.keys(formik.errors)[0])[0].focus() is undefined
but if the first div passes validation and error is on input box it works fine
const mortgageData = [
"Estou a obter um crédito habitação",
"Quero comparar com o seguro que tenho ",
"O meu seguro renova em breve",
];
const formik = useFormik({
initialValues: {
insuranceMotive: null,
creditCapital: null,
},
onSubmit: (values) => {
console.log(values);
},
validationSchema: validationSchemaSectionOne, //schema which validates the input with the help of Yup
});
useEffect(() => {
// this is the code which i tried but the problem is my first
// field is not input, its a <CheckTable/> component which
// is a div that has text in it, so this code scrolls to input
// box and ignores the first div, even it has errors
if (!formik.isSubmitting) return;
if (Object.keys(formik.errors).length > 0) {
document.getElementsByName(Object.keys(formik.errors)[0])[0].focus();
}
}, [formik]);
return (
<div className="firstSection">
<form onSubmit={formik.handleSubmit}>
<p className="tab-text">
Porque estás á procura de um Seguro Vida Crédito Habitação?
</p>
<div className="selectable-tags-mortgage">
{mortgageData.map((tag, index) => (
<CheckableTag
tag={tag}
key={index}
setValue={(val) => formik.setFieldValue("insuranceMotive", val)}
value={formik.values.insuranceMotive}
/>
))}
</div>
{formik.errors.insuranceMotive && formik.touched.insuranceMotive && (
<div className="formik-errors">{formik.errors.insuranceMotive}</div>
)}
<p className="tab-text">Qual o capital em € a cobrir pelo seguro? </p>
<Input
size="large"
name="creditCapital"
className="input-credit-capital"
value={formik.values.creditCapital}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.errors.creditCapital && formik.touched.creditCapital && (
<div className="formik-errors">{formik.errors.creditCapital}</div>
)}
<button type="submit" className="button-enabled">
CONTINUAR
</button>
</form>
</div>
);
}
CheckableTag component
export default function CheckableAntTag({ tag, value, setValue }) {
const { CheckableTag } = Tag
return (
<CheckableTag
style={{
backgroundColor: tag === value ? '#AACECD' : 'white'
}}
className="selectable-ant-tags"
key={tag}
checked={tag === value}
onChange={() => setValue(tag)}>
{tag}
</CheckableTag>
)
}
So if insuranceMotive is null, its an error as i have added required to that field, the error message gets logged successfully but i want to scroll to the CheckableTag section instead of input
Instead of using
Object.keys(formik.errors)[0])[0].focus()
you should use
Object.keys(formik.errors)[0])[0].scrollIntoView({ block: 'center'})
Object.keys(formik.errors)[0])[0].focus({ preventScroll: true})
I created a PasswordFields.vue file.
<template>
<div>
<el-form-item label="Mot de passe"
prop="password"
:error="this.registerForm.errors.get('password')"
required
:rules="[{ 'min': 6, message: 'Le mot de passe doit faire au moins 6 caractères', trigger: ['blur', 'change'] }]">
<el-input type="password" name="password" id="password" v-model="this.registerForm.password">
</el-input>
</el-form-item>
<!-- confirm password -->
<el-form-item label="Confirmation du mot de passe"
prop="password_confirmation"
:error="this.registerForm.errors.get('password_confirmation')"
required
:rules="[{ 'min': 6, message: 'Le mot de passe doit faire au moins 6 caractères', trigger: ['blur', 'change'] }]">
<el-input type="password" name="password_confirmation" id="password_confirmation" v-model="this.registerForm.password_confirmation">
</el-input>
</el-form-item>
</div>
</template>
Whenever I call my component in my Blade view, like this:
<password-fields></password-fields>
I have an error that says the property or method method is not defined on the instance but referenced during render.
I tried this, but it still does not work
<password-fields registerForm="registerForm"></password-fields>
Can you help me ? How to pass the value to my component? thank you very much
EDIT (the end of my component)
<script>
export default {
data() {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('Please input the password'));
} else {
if (this.registerForm.password_confirmation !== '') {
this.$refs.registerForm.validateField('password_confirmation');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('Please input the password again'));
} else if (value !== this.registerForm.password) {
callback(new Error('Two inputs don\'t match!'));
} else {
callback();
}
};
return {
rulesPass: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
]
}
}
}
}
never use this in the template
declare props in component
Example Component:
<template>
<div>
<el-form-item label="Mot de passe"
prop="password"
:error="registerForm.errors.get('password')"
required
:rules="[{ 'min': 6, message: 'Le mot de passe doit faire au moins 6 caractères', trigger: ['blur', 'change'] }]">
<el-input type="password" name="password" id="password" v-model="registerForm.password">
</el-input>
</el-form-item>
<!-- confirm password -->
<el-form-item label="Confirmation du mot de passe"
prop="password_confirmation"
:error="registerForm.errors.get('password_confirmation')"
required
:rules="[{ 'min': 6, message: 'Le mot de passe doit faire au moins 6 caractères', trigger: ['blur', 'change'] }]">
<el-input type="password" name="password_confirmation" id="password_confirmation" v-model="registerForm.password_confirmation">
</el-input>
</el-form-item>
</div>
</template>
<script>
export default {
data() {
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('Please input the password'));
} else {
if (this.registerForm.password_confirmation !== '') {
this.$refs.registerForm.validateField('password_confirmation');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('Please input the password again'));
} else if (value !== this.registerForm.password) {
callback(new Error('Two inputs don\'t match!'));
} else {
callback();
}
};
return {
rulesPass: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
]
}
}
}
}
props: ['registerForm'],
}
</script>
I'm not sure what I am doing wrong here. ReactJS is pretty new to me, so I need some help into the right direction.
What I want to achieve is when the span is clicked on a single list item, it should remove the list item. I created a removeHandler function on the parent component, and tried passing the function down via props.
The code compiles fine, but when I try to run it in the browser I get this in my console:
Uncaught TypeError: Cannot read property 'props' of undefined
at createTasks (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:9556:26)
at Array.map (native)
at Object.render (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:9562:33)
at file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:13530:21
at measureLifeCyclePerf (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:12809:12)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:13529:25)
at ReactCompositeComponentWrapper._renderValidatedComponent (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:13556:32)
at ReactCompositeComponentWrapper._updateRenderedComponent (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:13480:36)
at ReactCompositeComponentWrapper._performComponentUpdate (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:13458:10)
at ReactCompositeComponentWrapper.updateComponent (file:///C:/Users/Laurens/Desktop/ReactJS/output/myCode.js:13379:12)
Not sure what I am doing wrong,
I have these two components:
var TodoList = React.createClass({
getInitialState: function() {
return {
items: [] // De initial state (state wanneer het component gemount wordt) voor items wordt aangemaakt en is per definitie leeg.
};
},
addItem: function(e) {
var itemArray = this.state.items;
if(this._inputElement.value){ // Controleer of er een value is gepost. Een lege taak willen we immers niet toevoegen aan de todoItems.
itemArray.push( // Zoja, push dan een een nieuw item aan de itemArray.
{
text: this._inputElement.value, // De text van het volgende item is gelijk aan wat er in het textfield is ingevoerd.
key: Date.now() // De key moet uniek zijn, dus gebruiken we Date.now() voor een zoe goed als unieke key.
}
);
}
this.setState({
items: itemArray // Vervolgens update de state items met itemArray.
});
this._inputElement.value = "";// Het textfield wordt weer leeg gemaakt.
e.preventDefault();
},
handleRemove: function(id){
const remainder = this.state.data.filter((item) => {
if(item.key !== id) return item;
});
this.setState({
items: remainder
});
},
render: function() {
return (
<div className="todoListMain">
<div className="header">
<h3>ToDo lijst webapp</h3>
<form onSubmit={this.addItem}>
<input ref={(a) => this._inputElement = a} placeholder="enter task">
</input>
<button type="submit">add</button>
</form>
</div>
<TodoItems remove={this.handleRemove} entries={this.state.items}/>
</div>
);
}
});
And the following:
var TodoItems = React.createClass({
render: function() {
var todoEntries = this.props.entries;
function createTasks(item) {
return <li key={item.key}>{item.text}<span onClick={this.props.handleRemove(item.key)}>X</span></li>
}
var listItems = todoEntries.map(createTasks);
return (
<ul className="theList">
{listItems}
</ul>
);
}
});
var TodoItems = React.createClass({
render: function() {
var todoEntries = this.props.entries;
function createTasks(item) {
return <li key={item.key}>{item.text}<span onClick={() => this.props.remove(item.key)}>X</span></li>;
}
var listItems = todoEntries.map(createTasks,this);
return (
<ul className="theList">
{listItems}
</ul>
);
}
});
change <span onClick={this.props.handleRemove(item.key)
to <span onClick={this.props.remove(item.key) the props name is remove not handleRemove
and do todoEntries.map(createTasks, this); also this.props.remove.bind(this, item.key)
What David said is true, but you need to do an additional thing, so I'm copying David's answer along with the fix:
change <span onClick={this.props.handleRemove(item.key) to <span onClick={this.props.remove.bind(this)(item.key) the props name is remove not handleRemove