Reputation: 8291
I am learning reactjs and trying to implement small things for practice. The idea is simple, to add records (feedbackTasks
) to the database and list these records (when first time page is loaded and later when a new record is added). Please see the image below.
The main component is ManageFeedbackTasks
. I keep the list of the feedbackTask
items in its state (st_feedbackTaskList
). The update of this list is performed through add_to_st_feedbackTask
function. If the first time this list is generated, all the fetched data (coming from PrintFeedbackTasks
component) is set to the st_feedbackTaskList
. If not, only the added item (coming from ShowAddingFeedbackTaskForm
) is inserted in the list.
export function ManageFeedbackTasks() {
const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);
const add_to_st_feedbackTask = (data) => {
if (st_feedbackTaskList.length == 0) {
setFeedbackTaskList(data);
} else {
const { id, title, description } = data;
setFeedbackTaskList([...st_feedbackTaskList, { id, title, description }]);
}
}
return (
<>
<ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
<PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
</>
);
}
Below is the PrintFeedbackTasks
function. This function receives the feedbackTasks
list from the main component ManageFeedbackTasks
. This list is first time fetched from the database using fetchFeedbackTasks
. Inside fetchFeedbackTasks
, props.onListingFeedbackTasks(response.data)
sends the fetched list back to the main component to update the state (st_feedbackTaskList
).
const PrintFeedbackTasks = (props) => {
const [st_isInitialized, setInitialized] = useState(false);
const fetchFeedbackTasks = () => {
axios.get('api/FeedbackTask/Index')
.then(response => props.onListingFeedbackTasks(response.data))
.catch(error => console.log(error));
}
useEffect(() => {
if (!st_isInitialized) {
fetchFeedbackTasks();
}
setInitialized(true);
});
return (
<React.Fragment>
{
props.feedbackTasks.map(taskItem =>....
}
</React.Fragment>
);
}
The component below displays the Add form and handles the form submission. When a new item is added, this new item is again sent back to the main component using props.onAddingItem
.
const ShowAddingFeedbackTaskForm = (props) => {
const [st_title, setTitle] = useState('');
const [st_description, setDescription] = useState('');
const handleSubmit = async (event) => {
event.preventDefault();
await axios(...)
.then(function (response) {
setTitle('');
setDescription('');
//This will update the list of the feedback task in the main component
props.onAddingItem({
id: response.data,
title: st_title,
description: st_description
});
//GET THE ID HERE
console.log(response.data);
}).catch(function (error) {
console.log(error);
});
}
return (
<form onSubmit={handleSubmit}>
<input
placeholder="Title..."
type="text"
value={st_title}
onChange={(event) => setTitle(event.target.value)}
/>
<input
placeholder="Description..."
type="text"
value={st_description}
onChange={(event) => setDescription(event.target.value)}
/>
<button>Add Feedback Task</button>
</form>
);
}
I wonder if this way of lifting and managing the state is robust. Any suggestions to improve the code? Also, I wonder if I should put these components into their own pages (for example, one page or adding a record and another one for listing). Would this make more sense in the react
world?
Upvotes: 1
Views: 884
Reputation: 281666
The idea to lift the state up to the parent is correct. However due to your code structure you could be causing a lot of re-renders and a few performance optimizations can be made in your solution. One more thing is that instead of fetching feedbackTasks in PrintFeedbackTasks
component you should do it in the parent itself. Also useEffect takes a second parameter which you can use to execute it on initial mount
You can use useCallback
hook to memoize functions too.
ManageFeedbackTasks
export function ManageFeedbackTasks() {
const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);
const fetchFeedbackTasks = useCallback(() => {
axios.get('api/FeedbackTask/Index')
.then(response => props.onListingFeedbackTasks(response.data))
.catch(error => console.log(error));
}, []);
useEffect(() => {
fetchFeedbackTasks();
}, []);
const add_to_st_feedbackTask = useCallback((data) => {
setFeedbackTaskList(prevTaskList => {
if (prevTaskList.length == 0) {
return data;
} else {
const { id, title, description } = data;
return [...prevTaskList, { id, title, description }];
}
});
}, [])
return (
<>
<ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
<PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
</>
);
}
PrintFeedbackTasks
const PrintFeedbackTasks = (props) => {
return (
<React.Fragment>
{
props.feedbackTasks.map(taskItem =>....
}
</React.Fragment>
);
}
As far as the idea to split show and update TaskList is concerned it as product decision which can be made depending on how long is the list of fields that the user needs to fill at once
Upvotes: 1