getting error "Custom url is exist" in NextJS - reactjs

I'm having a problem when I input a new url in the project's custom url.
So this url input can be edited, now when it can be edited I enter a new url behind "https://www.kutanya.com/share/", then I save and a notification "custom url is exist" appears.
my API =
export const setCustomUrl = (args, surveyId) => {
return new Promise((resolve, reject) => {
axios
.put(process.env.NEXT_PUBLIC_API_URL + `/v1/smart-survey/${surveyId}/custom-url`, args, {
headers: { Authorization: `Bearer ${token()}` },
})
.then((response) => {
resolve(response.data.data);
})
.catch((error) => {
console.log(error.response);
reject(error?.response?.data?.message || "Network error.");
});
});
};
file .jsx =
const ShareKey = ({ customUrl, surveyId, shareKey = "", setShareKey, updateUrl, refProps }) => {
const [isLoading, setIsLoading] = useState(false);
const [customInput, setCustomInput] = useState(process.env.NEXT_PUBLIC_SHARE_URL + "/");
const [active, setActive] = useState(false);
const [show, setShow] = useState(false);
const router = useRouter();
const getLink = () => {
setShareKey("");
setIsLoading(true);
automaticApproval({ surveyId })
.then((resolve) => {
console.log(resolve);
setShareKey(resolve.key);
})
.catch((reject) => {
console.log(reject);
toast.error(reject);
})
.finally(() => {
setIsLoading(false);
});
};
const toggleFunction = () => {
setActive(!active);
setShow(!show);
};
const SaveFunction = () => {
setCustomUrl({ customUrl }, router.query.surveyId)
.then((resolve) => {
console.log(resolve);
updateUrl({
customUrl
});
setShareKey(resolve.key);
toast.info("Berhasil ubah link");
})
.catch((reject) => {
console.log(reject);
toast.error(reject);
})
.finally(() => {
setIsLoading(false);
});
};
return (
<section>
<button onClick={getLink} disabled={isLoading} className={styles.link_button}>
{`GENERATE ${shareKey && "NEW "}LINK`}
</button>
{shareKey && (
<div className={styles.link_container}>
<label>Share link</label>
<div className={styles.link}>
<input
value={active ? customInput : process.env.NEXT_PUBLIC_SHARE_URL + "/" + shareKey}
onChange={(e) => {
setCustomInput(e.target.value);
}}
disabled={!active}
ref={refProps}
/>
{!show && (
<button
onClick={() => {
if (typeof navigator !== "undefined") {
navigator.clipboard.writeText(refProps.current.value);
toast.info("Copied to clipboard");
}
}}
>
copy
</button>
)}
</div>
{active ? (
<div className={styles.custom2}>
<button style={{ color: "red", marginTop: "6px" }} onClick={toggleFunction}>
Cancel
</button>
<button style={{ color: "blue", marginTop: "6px" }} onClick={SaveFunction}>
Save
</button>
</div>
) : (
<div className={styles.custom} onClick={toggleFunction}>
Create Custom URL
</div>
)}
</div>
)}
</section>
);
};
The question is, is there something wrong in my coding so that the output is 400 in the console and the notification appears?

Related

Warning: Failed prop type: The prop `onSubmit` is marked as required in `ProjectWizardForm`, but its value is `undefined`

This error is shown in the browser console when Dialog (modal) is open:
Warning: Failed prop type: The prop onSubmit is marked as required
in ProjectWizardForm, but its value is undefined.
Code:
const UstHomeToolbar = ({ destroyProjectWizardForm, handleOpenAddPattern }) => {
const [open, setOpen] = useState(false);
const [openUploadForm, setOpenUploadForm] = useState(false);
const [projectWizardModalTitle, setProjectWizardModalTitle] = useState("");
const classes = useStyles();
const [selectedFile, setSelectedFile] = useState();
const [isFilePicked, setIsFilePicked] = useState(false);
const [statusText, setStatusText] = useState({
type: null,
msg: null,
});
const [userData, setUserData] = useState({});
useEffect(() => {
const userDataForPermissions = localStorage.getItem(LOGGED_IN_USER);
setUserData(JSON.parse(userDataForPermissions));
}, []);
const handleProjectDialogClickOpen = () => {
setOpen(true);
};
const handleProjectDialogClose = async () => {
setOpen(false);
};
const changeUploadHandler = (event) => {
setSelectedFile(event.target.files[0]);
setIsFilePicked(true);
};
const clearUploadHandler = (event) => {
setSelectedFile(null);
setIsFilePicked(false);
};
const handleUploadSubmission = () => {
const formData = new FormData();
formData.append("excel", selectedFile);
axios
.post("/project/excel", formData, {
headers: { "Content-Type": "multipart/form-data" },
})
.then((res) => {
clearUploadHandler();
setStatusText({
type: "success",
msg: "Excel file is uploaded successfully and taking you to the design....",
});
const design = res.data;
window.location.href = `/project/${design.project_id}/design/${design.id}`;
})
.catch((err) => {
console.error("Error:", err?.response?.data?.message);
clearUploadHandler();
setStatusText({
type: "error",
msg: err?.response?.data?.message,
});
});
};
const handleProjectDialogExited = () => {
destroyProjectWizardForm();
};
const handleProjectWizardModalTitle = (newModalTitle) =>
setProjectWizardModalTitle(newModalTitle);
return (
<Toolbar className={classes.toolbarHome}>
<Grid container justify="space-between">
<Grid item>
<Box className={classes.projectTitleStyle}>Projects</Box>
<Box className={classes.projectTitleDetailsStyle}>
List of ongoing and finished projects
</Box>
</Grid>
<Grid item>
<div className={classes.addProjectButtonStyle}>
<IxButton
onClick={() => setOpenUploadForm(true)}
handleClose={() => setOpenUploadForm(false)}
customClassName={TOOLBAR_BUTTON}
text="UPLOAD EXCEL"
inline={true}
disabled={!getPermission(userData, PROJECT).can_edit}
/>
<IxButton
onClick={handleProjectDialogClickOpen}
customClassName={TOOLBAR_BUTTON}
text="ADD PROJECT"
inline={true}
disabled={!getPermission(userData, PROJECT).can_edit}
/>
</div>
</Grid>
</Grid>
<IxDialog
handleClose={() => setOpenUploadForm(false)}
open={openUploadForm}
modalTitle={"Upload Design Excel"}
>
<div style={{ minHeight: "50px" }}>
Select an excel (*.xls) file:
<input
type="file"
onChange={changeUploadHandler}
accept=".xls"
style={{ marginLeft: "10px" }}
/>
</div>
<div style={{ marginBottom: "5px" }}>
{statusText.type && (
<Alert className={classes.statusText} severity={statusText.type}>
{statusText.msg}{" "}
</Alert>
)}
</div>
<div>
<Button
variant="contained"
component="label"
onClick={handleUploadSubmission}
disabled={!isFilePicked}
>
Upload File
</Button>
</div>
</IxDialog>
<IxDialog
handleClose={handleProjectDialogClose}
onExited={handleProjectDialogExited}
open={open}
modalTitle={projectWizardModalTitle}
>
<ProjectWizardForm
handleOpenAddPattern={handleOpenAddPattern}
handleClose={handleProjectDialogClose}
handleProjectWizardModalTitle={handleProjectWizardModalTitle}
/>
</IxDialog>
</Toolbar>
);
};
export default UstHomeToolbar;
ProjectWizardForm component:
const ProjectWizardForm = props => {
const [page, setPage] = useState(1);
const [touchedOnLoad, setTouchedOnLoad] = useState(false);
const history = useHistory();
const {
handleClose,
dispatch,
handleOpenAddPattern,
handleProjectWizardModalTitle
} = props;
useEffect(() => {
switch (page) {
case 1:
handleProjectWizardModalTitle('Add project');
break;
case 2:
handleProjectWizardModalTitle('Add target specs');
break;
case 3:
handleProjectWizardModalTitle('Add version details');
break;
default:
return;
}
}, [page, handleProjectWizardModalTitle]);
const saveData = values => {
const { submitButtonType } = values;
var errors = ProjectValidate(values);
if (Object.entries(errors).length > 0) {
if (errors?.number || errors?.drawn_date) {
setTouchedOnLoad(true);
setPage(1);
return;
} else if (errors.mandrel_id) {
setTouchedOnLoad(true);
setPage(3);
return;
}
}
const openAddPatternForm = newProject => {
const openAddPatternForm = true;
handleOpenAddPattern(openAddPatternForm, newProject);
};
dispatch(
addDesign(
formatProjectWizardSubmittedValue(values),
(err, newProject) => {
if (!err) {
dispatch(fetchProjects());
submitButtonType === ADD_PATTERN_NEXT_SUBMIT_BUTTON_TYPE
? openAddPatternForm(newProject)
: history.push(
`/project/${newProject.project_id}/details/${newProject.id}`
);
} else {
dispatch(setError(getFormatError(err)));
}
}
)
);
handleClose();
};
return (
<div>
{page === 1 && (
<UstProjectDetailForm
getDialogActionButtons={getAddProjectDetailsDialogActionButtons}
{...props}
touchedOnLoad={touchedOnLoad}
onSubmit={saveData}
nextPage={() => setPage(page + 1)}
/>
)}
{page === 2 && (
<UstProjectTargetSpecForm
{...props}
getDialogActionButtons={getAddTargetSpecDialogActionButtons}
onSubmit={saveData}
previousPage={() => setPage(page - 1)}
nextPage={() => setPage(page + 1)}
/>
)}
{page === 3 && (
<UstDesignDetailForm
{...props}
getDialogActionButtons={getAddDesignDetailsDialogActionButtons}
touchedOnLoad={touchedOnLoad}
onSubmit={saveData}
previousPage={() => setPage(page - 1)}
nextPage={() => setPage(page + 1)}
/>
)}
</div>
);
};
ProjectWizardForm.propTypes = {
onSubmit: PropTypes.func.isRequired
};
How can I fix this issue?

change menu in nextJS / reactJS

here I have a case where when I click a link "create custom url" it will change to "cancel" and "save".
for example like this :
When I click "create custom url"
Turned into like this
Want it like that.
However, when I try to make it this is the result
Cancel and save together, cancel and save should have its own function.
This is my code:
const ShareKey = ({ surveyId, shareKey = "", setShareKey, refProps }) => {
const [isLoading, setIsLoading] = useState(false);
const [customInput, setCustomInput] = useState(process.env.NEXT_PUBLIC_SHARE_URL + "/");
const [active, setActive] = useState(false);
const [show, setShow] = useState(false);
const getLink = () => {
setShareKey("");
setIsLoading(true);
automaticApproval({ surveyId })
.then((resolve) => {
console.log(resolve);
setShareKey(resolve.key);
})
.catch((reject) => {
console.log(reject);
toast.error(reject);
})
.finally(() => {
setIsLoading(false);
});
};
return (
<section>
<button onClick={getLink} disabled={isLoading} className={styles.link_button}>
{`GENERATE ${shareKey && "NEW "}LINK`}
</button>
{shareKey && (
<div className={styles.link_container}>
<label>Share link</label>
<div className={styles.link}>
<input
value={active ? customInput : process.env.NEXT_PUBLIC_SHARE_URL + "/" + shareKey}
onChange={(e) => {
setCustomInput(e.target.value);
}}
disabled={!active}
ref={refProps}
/>
{!show &&
<button
onClick={() => {
if (typeof navigator !== "undefined") {
navigator.clipboard.writeText(refProps.current.value);
toast.info("Copied to clipboard");
}
}}
>
copy
</button>
}
</div>
<p className={styles.custom} onClick={() => {setActive(!active); setShow(!show);}}>
{active ? "Cancel " + " Save" : "Create Custom URL"}
</p>
</div>
)}
</section>
);
};
Is there something wrong in my code? Please help. Thank you
This is how you gonna do it.
Also I changed your <p> to <div>. You can't nest anything inside of it.
You can change the container <div> to React Fragment if you don't want have some additional div.
You also have to fix the style.
const ShareKey = ({ surveyId, shareKey = "", setShareKey, refProps }) => {
const [isLoading, setIsLoading] = useState(false);
const [customInput, setCustomInput] = useState(
process.env.NEXT_PUBLIC_SHARE_URL + "/"
);
const [active, setActive] = useState(false);
const [show, setShow] = useState(false);
const getLink = () => {
setShareKey("");
setIsLoading(true);
automaticApproval({ surveyId })
.then((resolve) => {
console.log(resolve);
setShareKey(resolve.key);
})
.catch((reject) => {
console.log(reject);
toast.error(reject);
})
.finally(() => {
setIsLoading(false);
});
};
const toggleFunction = () => {
setActive(!active);
setShow(!show);
};
return (
<section>
<button
onClick={getLink}
disabled={isLoading}
className={styles.link_button}
>
{`GENERATE ${shareKey && "NEW "}LINK`}
</button>
{shareKey && (
<div className={styles.link_container}>
<label>Share link</label>
<div className={styles.link}>
<input
value={
active
? customInput
: process.env.NEXT_PUBLIC_SHARE_URL + "/" + shareKey
}
onChange={(e) => {
setCustomInput(e.target.value);
}}
disabled={!active}
ref={refProps}
/>
{!show && (
<button
onClick={() => {
if (typeof navigator !== "undefined") {
navigator.clipboard.writeText(refProps.current.value);
toast.info("Copied to clipboard");
}
}}
>
copy
</button>
)}
</div>
{active ? (
<div>
<button onClick={toggleFunction}>Cancel</button>
<button onClick={yourSaveFunction}>Save</button>
</div>
) : (
<div className={styles.custom} onClick={toggleFunction}>
Create Custom URL
</div>
)}
</div>
)}
</section>
);
};

How should I modify React state? addDoc() called with invalid data

I would like to upload a image-file to storage of the firebase and put {title , content, createDate etc} in firestore.
but it seems that state.upload file prevents putting it in firestore.
this.setState({ uploadfile: "" })
The error says
FirebaseError: Function addDoc() called with invalid data. Unsupported field value: a custom File object (found in field uploadfile in document projects/c0hQXdRAgIe1lIzq1vTy)
class CreateProject extends Component {
state = {
title:'',
content:'',
uploadfile:'',
setImageUrl:'',
}
handleChange = (e) =>{
this.setState({
[e.target.id]: e.target.value
})
}
handleSubmit = (e) =>{
e.preventDefault();
this.setState({ uploadfile: "" })
this.props.createProject(this.state)
this.props.history.push('/')
}
onDrop = acceptedFiles => {
if (acceptedFiles.length > 0) {
this.setState({ uploadfile: acceptedFiles[0] })
}
}
handleSubmitImg = (e) =>{
e.preventDefault()
//this.props.sampleteFunction()
};
parseFile = (file) =>{
const updatedFile = new Blob([file], { type: file.type });
updatedFile.name = file.name;
return updatedFile;
}
onSubmit = (event) => {
event.preventDefault();
var updatedFile = this.state.uploadfile;
if (updatedFile === "") {
}
console.log("aaaaaaaaaaaa"+updatedFile)
const uploadTask = storage.ref(`/images/${updatedFile.name}`).put(updatedFile);
uploadTask.on(
firebase.storage.TaskEvent.STATE_CHANGED,
this.next,
this.error,
this.complete
);
};
next = snapshot => {
const percent = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
};
error = error => {
console.log(error);
};
complete = () => {
var updatedFile = this.state.uploadfile
storage
.ref("images")
.child(updatedFile.name)
.getDownloadURL()
.then(fireBaseUrl => {
this.setState({ setImageUrl: fireBaseUrl })
//this.state.setImageUrl(fireBaseUrl);
});
};
render() {
const maxSize = 3 * 1024 * 1024;
const dropzoneStyle = {
width: "100%",
height: "auto",
borderWidth: 2,
borderColor: "rgb(102, 102, 102)",
borderStyle: "dashed",
borderRadius: 5,
}
const {auth} = this.props
console.log("UP"+this.state.uploadfile );
if(!auth.uid) return <Redirect to="/signin" />
return (
<Dropzone
onDrop={this.onDrop}
accept="image/png,image/jpeg,image/gif,image/jpg"
inputContent={(files, extra) => (extra.reject ? 'Image files only' : 'Drag Files')}
styles={dropzoneStyle}
minSize={1}
maxSize={maxSize}
>
{({ getRootProps, getInputProps }) => (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">
Create Project
</h5>
<div className="input-field">
<label htmlFor="title">Title</label>
<input type="text" id="title" onChange={this.handleChange}/>
</div>
<div className="input-field">
<label htmlFor="content">Project Content</label>
<textarea id="content" className="materialize-textarea" onChange={this.handleChange}></textarea>
</div>
<div className="input-field">
<button className="btn pink lighten-1 z-depth-0">Create</button>
</div>
</form>
<div {...getRootProps()}>
<input {...getInputProps()} />
<p>File Drag</p>
{this.state.uploadfile ? <p>Selected file: {this.state.uploadfile.name}</p> : null}
{this.state.uploadfile ? (<Thumb key={0} file={this.state.uploadfile } />) :null}
</div>
<form onSubmit={this.onSubmit}>
<button>Upload</button>
</form>
</div>
)}
</Dropzone>
)
}
}
const matchStateToProps = (state) => {
return{
auth: state.firebase.auth
}
}
const mapDispatchToProps = (dispatch) => {
return{
createProject: (project) => dispatch(createProject(project))
}
}
export default connect(matchStateToProps, mapDispatchToProps)(CreateProject)
Action
export const createProject = (project) => {
return (dispatch, getState, { getFirebase, getFirestore }) => {
// make async call to database
const firestore = getFirestore(); 
const profile = getState().firebase.profile;
const authorId = getState().firebase.auth.uid;
firestore.collection('projects').add({
...project,
authorUserName: profile.userName,
authorId: authorId,
createdAt: new Date()
}).then(() => {
dispatch({ type: 'CREATE_PROJECT', project})
}).catch((err) => {
dispatch({ type: 'CREATE_PROJECT_ERROR', err })
})
}
};

React state prevents uploading in react-redux

How Should I solve this problem?
After uploading an image by react state, this state seems to prevents putting props"project" in Action in Redux.
this.setState({ uploadfile: "" })
The error says
FirebaseError: Function addDoc() called with invalid data. Unsupported field value: a custom File object (found in field uploadfile in document projects/c0hQXdRAgIe1lIzq1vTy)
class CreateProject extends Component {
state = {
title:'',
content:'',
uploadfile:'',
setImageUrl:'',
}
handleChange = (e) =>{
this.setState({
[e.target.id]: e.target.value
})
}
handleSubmit = (e) =>{
e.preventDefault();
this.setState({ uploadfile: "" })
this.props.createProject(this.state)
this.props.history.push('/')
}
onDrop = acceptedFiles => {
if (acceptedFiles.length > 0) {
this.setState({ uploadfile: acceptedFiles[0] })
}
}
handleSubmitImg = (e) =>{
e.preventDefault()
//this.props.sampleteFunction()
};
parseFile = (file) =>{
const updatedFile = new Blob([file], { type: file.type });
updatedFile.name = file.name;
return updatedFile;
}
onSubmit = (event) => {
event.preventDefault();
var updatedFile = this.state.uploadfile;
if (updatedFile === "") {
}
console.log("aaaaaaaaaaaa"+updatedFile)
const uploadTask = storage.ref(`/images/${updatedFile.name}`).put(updatedFile);
uploadTask.on(
firebase.storage.TaskEvent.STATE_CHANGED,
this.next,
this.error,
this.complete
);
};
next = snapshot => {
const percent = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
};
error = error => {
console.log(error);
};
complete = () => {
var updatedFile = this.state.uploadfile
storage
.ref("images")
.child(updatedFile.name)
.getDownloadURL()
.then(fireBaseUrl => {
this.setState({ setImageUrl: fireBaseUrl })
//this.state.setImageUrl(fireBaseUrl);
});
};
render() {
const maxSize = 3 * 1024 * 1024;
const dropzoneStyle = {
width: "100%",
height: "auto",
borderWidth: 2,
borderColor: "rgb(102, 102, 102)",
borderStyle: "dashed",
borderRadius: 5,
}
const {auth} = this.props
console.log("UP"+this.state.uploadfile );
if(!auth.uid) return <Redirect to="/signin" />
return (
<Dropzone
onDrop={this.onDrop}
accept="image/png,image/jpeg,image/gif,image/jpg"
inputContent={(files, extra) => (extra.reject ? 'Image files only' : 'Drag Files')}
styles={dropzoneStyle}
minSize={1}
maxSize={maxSize}
>
{({ getRootProps, getInputProps }) => (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">
Create Project
</h5>
<div className="input-field">
<label htmlFor="title">Title</label>
<input type="text" id="title" onChange={this.handleChange}/>
</div>
<div className="input-field">
<label htmlFor="content">Project Content</label>
<textarea id="content" className="materialize-textarea" onChange={this.handleChange}></textarea>
</div>
<div className="input-field">
<button className="btn pink lighten-1 z-depth-0">Create</button>
</div>
</form>
<div {...getRootProps()}>
<input {...getInputProps()} />
<p>File Drag</p>
{this.state.uploadfile ? <p>Selected file: {this.state.uploadfile.name}</p> : null}
{this.state.uploadfile ? (<Thumb key={0} file={this.state.uploadfile } />) :null}
</div>
<form onSubmit={this.onSubmit}>
<button>Upload</button>
</form>
</div>
)}
</Dropzone>
)
}
}
const matchStateToProps = (state) => {
return{
auth: state.firebase.auth
}
}
const mapDispatchToProps = (dispatch) => {
return{
createProject: (project) => dispatch(createProject(project))
}
}
export default connect(matchStateToProps, mapDispatchToProps)(CreateProject)
Action
export const createProject = (project) => {
return (dispatch, getState, { getFirebase, getFirestore }) => {
// make async call to database
const firestore = getFirestore(); 
const profile = getState().firebase.profile;
const authorId = getState().firebase.auth.uid;
firestore.collection('projects').add({
...project,
authorUserName: profile.userName,
authorId: authorId,
createdAt: new Date()
}).then(() => {
dispatch({ type: 'CREATE_PROJECT', project})
}).catch((err) => {
dispatch({ type: 'CREATE_PROJECT_ERROR', err })
})
}
};

How do I write test for hooks?

I am making unit test for the component and also trying to make a test for hook but I can't seem to get it working. This is my hook. What do I need to change or do to fix this test?
import { useState } from 'react';
function UseToggleState (initialValue = false) {
const [state, setState] = useState(initialValue);
const toggle = () => setState(!state);
return [state, toggle];
};
export default UseToggleState
And this is the component I am using it.
export function Todo({ id, task, completed }) {
const classes = useStyles();
const dispatch = useContext(DispatchContext);
const [isEditing, toggle] = useToggleState(false);
if (isEditing) {
return (
<li
className={classes.Todo}
style={{ overflowY: "hidden" }}
onClick={() => toggle()}
>
<EditForm id={id} task={task} toggleEditForm={toggle} />
</li>
);
}
return (
<li
className={classes.Todo}
onClick={() => dispatch({ type: TOGGLE_TODO, id })}
>
<span
style={{
textDecoration: completed ? "line-through" : "",
color: completed ? "#A9ABAE" : "#34495e",
}}
>
{task}
</span>
<div className={classes.icons}>
<FontAwesomeIcon
icon={faPen}
size="1x"
onClick={(e) => {
e.stopPropagation();
toggle();
}}
/>{" "}
<FontAwesomeIcon
icon={faTrash}
size="1x"
color={"#c0392b"}
onClick={(e) => {
e.stopPropagation();
dispatch({ type: REMOVE_TODO, id });
}}
/>
</div>
</li>
);
}
And the test file is as follows. It keeps saying that toggle is not a function and I am not quite sure why it is doing that. Is there something I need to change differently to make it work?
describe("useToggleState", () => {
it("Initial toggle is true", () => {
const { result } = renderHook(() => UseToggleState(true))
act(() => {
result.current.toggle
})
expect(result.current.state).toBeTruthy()
})
it("Toggle is false", () => {
const { result } = renderHook(() => UseToggleState(false))
act(() => {
result.current.toggle
})
expect(result.current.state).toBeFalsy()
})
})
You test is supposed to be:
describe("useToggleState", () => {
it("Initial toggle is false", () => {
const { result } = renderHook(() => UseToggleState(true))
act(() => {
result.current[1]()
})
expect(result.current[0]).toBe(false)
})
it("Toggle is true", () => {
const { result } = renderHook(() => UseToggleState())
act(() => {
result.current[1]()
})
expect(result.current[0]).toBe(true)
})
})

Resources