I have found many questions similar to this and answers to those questions, but I haven’t found an answer that I have figured out how to apply to my problem yet. The app loads fine and displays the form, but doesn’t create a table upon submit. I’m still learning how to use props effectively so I’m not sure where I’m going wrong yet.
I get the following error when I try to submit the form;
Uncaught TypeError: props.func is not a function
transferValue AddCombatantTable.jsx:33
React 14
unstable_runWithPriority scheduler.development.js:468
React 15
js index.js:7
factory react refresh:6
Webpack 3
I am trying to create a form that creates a table based on this.
Here is AddCombatantTable.jsx;
import React, { useState } from 'react';
function CombatantForm(props) {
const [initiative, setInit] = useState('');
const [name, setName] = useState('');
const [armorClass, setAC] = useState('');
const [hitPoints, setHP] = useState('');
const changeInit = (event) => {
setInit(event.target.value);
};
const changeName = (event) => {
setName(event.target.value);
};
const changeAC = (event) => {
setAC(event.target.value);
};
const changeHP = (event) => {
setHP(event.target.value);
};
const transferValue = (event) => {
event.preventDefault();
const val = {
initiative,
name,
armorClass,
hitPoints,
};
props.func(val);
clearState();
};
const clearState = () => {
setInit('');
setName('');
setAC('');
setHP('');
};
return (
<div>
<label>Initiative</label>
<input type="text" value={initiative} onChange={changeInit} />
<label>Name</label>
<input type="text" value={name} onChange={changeName} />
<label>Armor Class</label>
<input type="text" value={armorClass} onChange={changeAC} />
<label>Hit Points</label>
<input type="text" value={hitPoints} onChange={changeHP} />
<button onClick={transferValue}>Add Combatant</button>
</div>
);
}
export default CombatantForm;
AddCombatantForm.jsx;
import React, { useState } from 'react';
import CombatantForm from './AddCombatantForm';
import jsonData from './data.json';
function TableData() {
const [combatantData, setCombatantData] = useState(jsonData);
const tableRows = combatantData.map((info) => {
return (
<tr>
<td>{info.id}</td>
<td>{info.initiative}</td>
<td>{info.name}</td>
<td>{info.armorClass}</td>
<td>{info.hitPoints}</td>
</tr>
);
});
const addRows = (data) => {
const totalCombatants = combatantData.length;
data.id = totalCombatants + 1;
const updatedCombatantData = [...combatantData];
updatedCombatantata.push(data);
setCombatantData(updatedCombatantData);
};
return (
<div>
<table className="table table-stripped">
<thead>
<tr>
<th>ID</th>
<th>Initiative</th>
<th>Name</th>
<th>Armor Class</th>
<th>Hit Points</th>
</tr>
</thead>
<tbody>{tableRows}</tbody>
</table>
<CombatantForm func={addRows} />
</div>
);
}
export default TableData;
App.js;
import TableData from './components/AddCombatantTable';
function App() {
return (
<div className="App">
<TableData />
</div>
);
}
export default App;