My first part of the project is using useState for the state control. Second part of the project is using Radux for state control.I am using react radux for state. I have select a movie in the Member.jsx for edit and I display it in DisplayChoooseMovie for edit. I use input tag to display the movie data. I am using reducer function showSelectMovieForEdit in recordSlice.js in AssignmentTwo folder to display the movie for edit. Then I use onChange in the info['movie name'] to update the 'movie name' in the movie date. I don't know why I can change the value of the name in the input tag. It always keep the name it had.
My DisplayChooseMovie.jsx
import { showSelectMovieForEdit, saveMovieAfterEdit, saveMovieChangeName } from "./RecordSlice";
import { useSelector, useDispatch } from 'react-redux';
export default function DisplayChooseMovie(){
const records = useSelector(function (store) {
return store.record.value;
});
const dispatch = useDispatch();
const tableRows =(records)=>
//Display the movie list in a table
records. Map((info,num) => {
return (
info.displayOneMovie && (
<div>
<input type={"text"} maxLength={"100"} value={info.id} ></input><br></br>
<input type={"text"} name={"moviesName"} id={"moviesName"} value={info['movie name']} onChange={(event)=>{saveMovieChangeName({"id":info.id, "movie name": event.target.value })}}></input><br></br>
<textarea id={"changeMovieDescription"} rows={"10"} cols={"20"} value={info.description}></textarea><br></br>
<input type={"text"} id={"changeMovieGenre"} value={info. Genre}></input><br></br>
<input type={"text"} id={"changeLeadActor"} value={info['lead actor']}></input><br></br>
<input type={"text"} id={"changeRating"} value={info.rating}></input><br></br>
<input type={"text"} id={"changeMovieLanguage"} value={info. Language}></input>
</div>
))
})
return (
<div>
{tableRows(records)}
<div style={{ marginTop:"10px",textAlign:"center" }}><input type={"button"} value={"Save Change Button"} onClick={()=>{dispatch(saveMovieAfterEdit(records))}}></input></div>
</div>)
}
My Member.jsx
import { useDispatch } from 'react-redux';
import { showSelectMovieForEdit } from '../AssignmentTwo/recordSlice';
export default function Member({data, ondeleteHandler, onChangeIdHandler, checkHideShowHandler, onClickShowItemHandler}){
const dispatch = useDispatch();
const tableRows =(data)=>
//Display the movie list in a table
data.map((info,num) => {
return (
info. Display && (
<tr key={info.id}>
<td style={{ border: "2px solid #696969", color: 'white', textAlign: 'center'}}>{info.id}</td>
<td style={{ border: "2px solid #696969", color: 'white', textAlign: 'center'}}>{info['movie name']}</td>
<td style={{ border: "2px solid #696969", color: 'white', textAlign: 'center', margin: '1px auto'}}>{info.description}</td>
<td style={{ border: "2px solid #696969", color: 'white'}}>{info.genre}</td>
{
info['lead actor'].map((data)=><td style={{ border: "2px solid #696969", color: 'white'}}>
{data}</td>)}
<td style={{ border: "2px solid #696969", color: 'white', textAlign: 'center'}}>{info. Rating}</td>
<td style={{ border: "2px solid #696969", color: 'white', textAlign: 'center'}}>{info. Language}</td>
<td style={{ border: "2px solid #696969", textAlign: "center" }}><input type={"checkbox"} id={"deletemovies"} name={"deletemovies"} onChange={(event) => onChangeIdHandler(event,info.id)}></input></td>
<td style={{ border: "2px solid #696969", textAlign: "center"}}><input type={"checkbox"} id={"showHideMovies"} name={"showHideMovies"} onChange={(event) => checkHideShowHandler(event,info.id)}></input></td>
<td style={{ border: "2px solid #696969", textAlign: "center"}}><input type={"checkbox"} id={"showHideMovies"} name={"showHideMovies"} onChange={(event) => dispatch(showSelectMovieForEdit(info.id))}></input></td>
</tr>
))
})
return (
<div>
<table style = {{ width: "100%", marginTop: "50px", backgroundColor: "black", borderCollapse: "collapse"}}>
<thead style={{ border: "2px solid #ea4915"}}>
<tr>
<th style={{ border: "2px solid #696969", color: 'white', backgroundColor: "black"}}>Id</th>
<th style={{ border: "2px solid #696969", color: 'white', backgroundColor: "black" }}>Name</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}}>Description of Movies</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}}>Genre</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}} colSpan={"2"}>Actors</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}}>Rating</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}}>Language</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}}>Remove Items</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}}>Hide Items</th>
<th style={{ border: "2px solid #696969" , color: 'white', backgroundColor: "black"}}>Select Movie for Edit</th>
</tr>
</thead>
<tbody>{tableRows(data)}</tbody>
</table>
<div className="buttonSeparation">
<ol style={{ textAlign: "center", listStyleType: "none", listStylePosition: "inside"}}>
<li style={{ border: "2px solid #696969", width: '89px', listStyle: "none", display: "inline-block"}}>
<input type={"button"} onClick= {ondeleteHandler} value={"Delete Items"}></input>
</li>
<li style={{ display: "inline-block", border: "2px solid #696969", width: '135px',marginLeft: "10px"}}>
<input type={"button"} value={"Show the hide items"} onClick={onClickShowItemHandler} ></input>
</li>
</ol>
</div>
</div>)
}
My recordSlice.js
import { createSlice } from '@reduxjs/toolkit';
import { datamovielist } from '../App';
export const recordSlice = createSlice({
name: 'Record Slice',
initialState: {
value: [
{ "id": 1,"movie name" : "Ticket to Paradise","display":"true","description":"Academy Award® winners George Clooney and Julia Roberts reunite on the big screen as exes who find themselves on a shared mission to stop their lovestruck daughter from making the same mistake they once made","genre" :"Comedy", "lead actor": ["George Clooney", "Julia Roberts"],"rating":5,"displayOneMovie":false,"language":"english"},
{ "id": 2, "movie name": "Black Panter","display":true,"description":"Queen Ramonda (Angela Bassett), Shuri (Letitia Wright), M’Baku (Winston Duke), Okoye (Danai Gurira) and the Dora Milaje (including Florence Kasumba), fight to protect their nation from intervening world powers in the wake of King T’Challa’s death.","genre":"Action","lead actor":["Angela Bassett","Letitia Wright"],"rating":6,"displayOneMovie":false,"language":"english"},
{ "id":3, "movie name": "Smile","display":true,"description":"After witnessing a bizarre, traumatic incident involving a patient, Dr. Rose Cotter (Sosie Bacon) starts experiencing frightening occurrences that she can't explain.","genre":"Drama","lead actor":["Sosie Bacon","Jessie T. Usher"],"rating":6,"displayOneMovie":false,"language":"english"},
{"id":4,"movie name":"Come Back Home","display":true,"description":"In the cold winter, a group of Shenzhen tourist families take a trip to the northeast Changbai Mountain. It was originally intended to be a happy and harmonious holiday, but due to the negligence of his father, an 8-year-old boy is unfortunately lost.","genre":"Mistery","lead actor":["Donnie Yen", "Han Xue"],"rating":6,"displayOneMovie":false,"language":"mandarian"},
{"id":5,"movie name":"Ajoomma","display":true,"description":"Auntie (Hong Huifang), is a middle-aged Singaporean woman who has dedicated the best years of her life to caring for her family. Now widowed with her grown up son, Sam (Shane Pow) about to fly the roost, Auntie is left to contend with a whole new identity beyond her roles of daughter, wife, and mother.","genre":"Drama","lead actor":["Hong Huifang", "Jung Dong-Hwan"],"rating":4,"displayOneMovie":false,"language":"mandarian"}
], // No records initially
},
reducers: {
showSelectMovieForEdit: function(state,action){
for(let i=0;i<state.value.length;i ){
if(state.value[i].id===action.payload){
state.value[i].displayOneMovie = true
}
}
},
saveMovieAfterEdit: function(state,action){
alert(action.payload)
},
saveMovieChangeName: function(state,action){
alert(action.payload)
},
},
});
// Use these to update the state in your component
export const { showSelectMovieForEdit, saveMovieAfterEdit, saveMovieChangeName } = recordSlice.actions;
// This part goes into the store.
export default recordSlice.reducer
My storage.js
import { configureStore } from '@reduxjs/toolkit'
import recordReducer from './recordSlice';
export default configureStore({
reducer: {
// Register reducers here
record: recordReducer
}
})
My App.js
import LoggedInForm from "./AssignmentOne/LoggedInForm"
import AddMember from "./AssignmentOne/AddMember";
import Member from "./AssignmentOne/Member";
import ChooseGenre from "./AssignmentOne/ChooseGenre";
import { Provider } from 'react-redux';
import storage from "./AssignmentTwo/storage";
import DisplayChooseMovie from "./AssignmentTwo/DisplayChooseMovie";
//Json data of movie list
const dataMovielist = [{ "id": 1,"movie name" : "Ticket to Paradise","display":"true","description":"Academy Award® winners George Clooney and Julia Roberts reunite on the big screen as exes who find themselves on a shared mission to stop their lovestruck daughter from making the same mistake they once made","genre" :"Comedy", "lead actor": ["George Clooney", "Julia Roberts"],"rating":5,"displayOneMovie":false,"language":"english"},
{ "id": 2, "movie name": "Black Panter","display":true,"description":"Queen Ramonda (Angela Bassett), Shuri (Letitia Wright), M’Baku (Winston Duke), Okoye (Danai Gurira) and the Dora Milaje (including Florence Kasumba), fight to protect their nation from intervening world powers in the wake of King T’Challa’s death.","genre":"Action","lead actor":["Angela Bassett","Letitia Wright"],"rating":6,"displayOneMovie":false,"language":"english"},
{ "id":3, "movie name": "Smile","display":true,"description":"After witnessing a bizarre, traumatic incident involving a patient, Dr. Rose Cotter (Sosie Bacon) starts experiencing frightening occurrences that she can't explain.","genre":"Drama","lead actor":["Sosie Bacon","Jessie T. Usher"],"rating":6,"displayOneMovie":false,"language":"english"},
{"id":4,"movie name":"Come Back Home","display":true,"description":"In the cold winter, a group of Shenzhen tourist families take a trip to the northeast Changbai Mountain. It was originally intended to be a happy and harmonious holiday, but due to the negligence of his father, an 8-year-old boy is unfortunately lost.","genre":"Mistery","lead actor":["Donnie Yen", "Han Xue"],"rating":6,"displayOneMovie":false,"language":"mandarian"},
{"id":5,"movie name":"Ajoomma","display":true,"description":"Auntie (Hong Huifang), is a middle-aged Singaporean woman who has dedicated the best years of her life to caring for her family. Now widowed with her grown up son, Sam (Shane Pow) about to fly the roost, Auntie is left to contend with a whole new identity beyond her roles of daughter, wife, and mother.","genre":"Drama","lead actor":["Hong Huifang", "Jung Dong-Hwan"],"rating":4,"displayOneMovie":false,"language":"mandarian"}]
function App(props){
//Initial movie item id
let moviesitemsid = [];
//Initial hide movie id
let hidemoviesid = [];
//useState of movieid, datamovielist, isLogin and hideshowmovieid
const [moviesid, setmoviesid] = React.useState(moviesitemsid);
const [datamovielist, setdatamovielist] = React.useState(dataMovielist);
const [isLogin, setIsLoggedIn] = React.useState(false)
const [hideshowmoviesid, sethideshowmoviesid] = React.useState(hidemoviesid);
//Add a new movie list to the original dataMovieList
const onSubmitHandler = (newHobbies) => {
setdatamovielist([...datamovielist, newHobbies]);
};
//Add a false boolean to the display if the id is the same
//so that we can hide the movie list
const checkHideShowHandler = (event, id) => {
if (event.target.checked === true) {
let copy = [...datamovielist];
for(let c=0; c< copy.length; c ){
if(id === copy[c].id){
copy[c].display = false;
}
}
setdatamovielist(copy);
if (hideshowmoviesid.length === 0) {
sethideshowmoviesid([id]);
} else {
addHideShowMoviesId(id);
}
} }
//Add a true to the display so that the hide movie
//appear again
const onClickShowItemHandler = () => {
let copy = [...datamovielist];
for (let i = 0; i < hideshowmoviesid.length; i ) {
for(let c=0; c< copy.length; c ){
if(hideshowmoviesid[i] === copy[c].id){
copy[c].display =true;
}
};
}
setdatamovielist(copy);
sethideshowmoviesid([]);
}
//Add a new movie id to the original id for the hide and show event
function addHideShowMoviesId(newmoviesid) {
sethideshowmoviesid([...hideshowmoviesid, newmoviesid]);
}
//Add a new movie id to the original movie id
function addMoviesId(newmoviesid) {
setmoviesid([...moviesid, newmoviesid]);
}
//Delete the movie list
const ondeleteHandler = (event) => {
event.preventDefault();
let copy = [...datamovielist];
for (let i = 0; i < moviesid.length; i ) {
copy = copy.filter((item, index) => moviesid[i] !== item.id);
}
setdatamovielist(copy);
setmoviesid([]);
};
//Check the movie Id whether it is the start of the movie data, then pass it to the movie id
//container. If it is not the start of the movies data, add it to the original movie id. Also
//delete it if the checkbox is not checked. This is for the ondeleteHandler. The movie id store
//the list of id in the movie data
const checkIdEventHandler = (event, id) => {
if (event.target.checked === true) {
if (moviesid.length === 0) {
setmoviesid([id]);
} else {
addMoviesId(id);
}
} else {
let copy = [...moviesid];
copy = copy.filter((data) => data !== id);
setmoviesid(copy);
}
};
//Show the movie according to the genre
function setgenreHandler(event,genrename){
event.preventDefault();
let data = [...datamovielist]
for(let i =0; i<data.length; i ){
if(genrename.toLowerCase() === data[i].genre.toLowerCase() ){
data[i].display= true;
}else {
data[i].display = false;
}
if(genrename.toLowerCase() === "none"){
for(let i=0; i < data.length; i ){
data[i].display = true;
}
}
}
setdatamovielist(data);
}
return(
<div>
<Provider store={storage}>
<LoggedInForm setIsLoggedIn = {setIsLoggedIn}/>
{
// isLogin &&
<div> <AddMember onSubmitHandler={onSubmitHandler} />
<Member data = {datamovielist} onClickShowItemHandler={onClickShowItemHandler} ondeleteHandler={ondeleteHandler} onChangeIdHandler={checkIdEventHandler} checkHideShowHandler={checkHideShowHandler} setgenreHandler={setgenreHandler}/>
<ChooseGenre setgenreHandler={setgenreHandler} />
<DisplayChooseMovie />
</div>}
</Provider>
</div>
)
}
export {dataMovielist}
const root = ReactDOM.createRoot(document.getElementById('root'));
root. Render(<App/>);
I am new to React. I don't know why I can't edit the movielist in DisplayChooseMovie. Please look at the code in Member.jsx, recordSlice.js, storage.js and DisplayChooseMovie.jsx as these are files that I added the new code. The rest of the code it ok. Hope you can sole for me. I never include some files as it is not important.Thanks
CodePudding user response:
<input type={"text"} maxLength={"100"} value={info.id}>
since value
= {info.id}
the input will always show info.id
if you want to change it's value, you need to update info.id
with onChange
saveMovieChangeName({"id":info.id, "movie name": event.target.value })
this is not updating, this is showing an alert
CodePudding user response:
In your reducer (recordSlice.js
) you have to update the state. Actually, you are just making an alert.
To do this, instead of having
saveMovieChangeName: function(state,action) {
alert(action.payload)
},
You should have
saveMovieChangeName: function(state,action) {
state.value[action.payload.id] = action.payload["movie name"] // <-- here is the update
alert(action.payload)
},