Reputation: 1792
I have three components which App is the parent component(class-based) and two children component(functional-based) named User & Input. I've imported User to App and Input to User. I want to change the name by the value in Input(there is a button -> onClick).
Updated The problem is the function in App.jsx(I'm pretty sure the way I try to do it is true).
// App.jsx
Imported User
state = {
users : [
{id: 1, fullName: 'Amirreza Amini'},
{id: 2, fullName: 'John Smith'},
...
]
};
handleChangeName = name => {
const editedUsers = [...this.state.users];
const users = editedUsers.map(user => user.fullName = name);
this.setState({ users });
};
render() {
const { users } = this.state;
const userComponent = users.map(user => (
<User
key={user.id}
fullName={user.fullName}
edit={() => this.handleChangeName(user.fullName)}
/>
));
.
// User.jsx
Imported Input
const User = ({ fullName }) => {
return (
<section>
<h1>{ fullName }</h1>
<Input fullName={fullName} />
</section>
);
};
export default User;
.
// Input.jsx
const Input = ({ fullName }) => {
return (
<section>
{/* The value of this input must be the fullName after I clicked the button */}
<input className="user-edit-input" placeholder={fullName} />
<button className="edit-button" onClick={edit(document.querySelector('.user-edit-input').value)}>Change</button>
</section>
);
};
export default Input;
Upvotes: 0
Views: 50
Reputation: 5444
Two big options as I see it:
Option one is changing App.jsx to functional component and send the function to change the fullname to User.jsx and the to Input.jsx as props letting the Input component change the value by itself
Option two that can leave your App.jsx component as is, keep it more secured and allow the child component to deal with only what it needs to actually know, is similarly sending a function from the parent App component so the Input component can trigger sending the old fullname and new fullname and the parent component function would handle the rest of the process.
example for parent function:
const updateFullname = (previousName, newName) => {
// Get previous object data and location in array
let originalUsersState = this.state.users;
let originalUser = originalUsersState.filter(
(user, index) => user.fullName === previousName
)
const originalUserIndex = originalUsersState.findIndex(
(user, index) => user.fullName === previousName
)
// Create new updated object and insert it to updated object array
let updatedUser = originalUser
updatedUser.fullName = newName;
let updatedUsersState = originalUsersState;
updatedUsersState[originalUserIndex] = updatedUser;
// Update the state with the new updated object array
this.setState(
{
users: updatedUsersState
}
);
}
Abbriviation for a solution for the question code with the new proposed function and process:
// App.jsx
Imported User
state = {
users : [
{id: 1, fullName: 'Amirreza Amini'},
{id: 2, fullName: 'John Smith'},
...
]
};
handleChangeName = name => {
const editedUsers = [...this.state.users];
const users = editedUsers.map(user => user.fullName = name);
this.setState({ users });
};
const updateFullname = (previousName, newName) => {
// Get previous object data and location in array
let originalUsersState = this.state.users;
let originalUser = originalUsersState.filter(
(user, index) => user.fullName === previousName
)
const originalUserIndex = originalUsersState.findIndex(
(user, index) => user.fullName === previousName
)
// Create new updated object and insert it to updated object array
let updatedUser = originalUser
updatedUser.fullName = newName;
let updatedUsersState = originalUsersState;
updatedUsersState[originalUserIndex] = updatedUser;
// Update the state with the new updated object array
this.setState(
{
users: updatedUsersState
}
);
}
render() {
const { users } = this.state;
const userComponent = users.map(user => (
<User
key={user.id}
fullName={user.fullName}
updateFullname={updateFullname}
edit={() => this.handleChangeName(user.fullName)}
/>
));
// User.jsx
Imported Input
const User = ({ fullName, updateFullname }) => {
return (
<section>
<h1>{ fullName }</h1>
<Input fullName={fullName} updateFullname={updateFullname} />
</section>
);
};
export default User;
// Input.jsx
const Input = ({ fullName }) => {
const [inputValue, setInputValue] = useState(undefined);
return (
<section>
<input className="user-edit-input" value={inputValue} onChange={event => setInputValue(event.target.value)} placeholder={fullName} />
<button className="edit-button" onClick={(fullname, inputValue) => updateFullname}>Change</button>
</section>
);
};
export default Input;
Upvotes: 1
Reputation: 202
You can send input as props to callback from User component. From Users, with the callback function, call one more function to set state in User component
Upvotes: 1