В JSX {...}
выводит результат выражения внутри него. (Вы полагаетесь на это в другом месте, например className={classes.InputText}
.) Вы оцениваете setTimeout
в {}
, который возвращает дескриптор таймера, который является числом.
Вы не должны быть используя setTimeout
в вашем JSX вообще. Вместо этого просто запустите его в теле вашего компонента, , если , вы действительно хотите, чтобы он запускался каждый раз, когда ваш компонент отображается:
const Chat = () => {
const [showInputText, setShowInputText] = useState(false)
const typistCursor = {
hideWhenDone: true,
hideWhenDoneDelay: 200,
}
const inputText = (<Typist cursor={typistCursor}>test@mail.com</Typist>)
// *** Moved
setTimeout(() => {
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
return (
<div className={classes.EmailInput}>
{showInputText ? (inputText) : (<div className={classes.InputText}>Indtast din email her...</div>)}
</div>
)
}
Live Пример:
const { useState } = React;
const classes = {
InputText: {
color: "green"
}
};
const Chat = () => {
const [showInputText, setShowInputText] = useState(false)
const typistCursor = {
hideWhenDone: true,
hideWhenDoneDelay: 200,
}
// *** Replaced Typist here just for demo purposes
const inputText = (<div>test@mail.com</div>)
// *** Moved
setTimeout(() => {
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
return (
<div className={classes.EmailInput}>
{showInputText ? (inputText) : (<div className={classes.InputText}>Indtast din email her...</div>)}
</div>
)
}
ReactDOM.render(<Chat />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
Но , учтите, что если сделать setTimeout
безусловным, вы будете продолжать делать это снова и снова, даже если showInputText
уже true
. Если вы хотите сделать это только тогда, когда оно false
, добавьте ветку:
const Chat = () => {
const [showInputText, setShowInputText] = useState(false)
const typistCursor = {
hideWhenDone: true,
hideWhenDoneDelay: 200,
}
const inputText = (<Typist cursor={typistCursor}>test@mail.com</Typist>)
// *** Added `if`
if (!showInputText) {
// *** Moved
setTimeout(() => {
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
}
return (
<div className={classes.EmailInput}>
{showInputText ? (inputText) : (<div className={classes.InputText}>Indtast din email her...</div>)}
</div>
)
}
Live Пример:
const { useState } = React;
const classes = {
InputText: {
color: "green"
}
};
const Chat = () => {
const [showInputText, setShowInputText] = useState(false)
const typistCursor = {
hideWhenDone: true,
hideWhenDoneDelay: 200,
}
// *** Replaced Typist here just for demo purposes
const inputText = (<div>test@mail.com</div>)
// *** Added `if`
if (!showInputText) {
// *** Moved
setTimeout(() => {
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
}
return (
<div className={classes.EmailInput}>
{showInputText ? (inputText) : (<div className={classes.InputText}>Indtast din email her...</div>)}
</div>
)
}
ReactDOM.render(<Chat />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
В комментарии вы сказали, что беспокоитесь о времени ожидания, которое начинается до показа компонента, и о том, что время ожидания должно начинаться только тогда, когда state >= 6
. Для этого используйте обратный вызов useEffect
с state
(и showInputText
) в качестве зависимостей и установите таймер, если !showInputText && state >= 6
:
// *** `useEffect` depending on `state` and `showInputText`
useEffect(() => {
// You'll see this console log every time the component is rendered
// with an updated `showInputText` or `state`
console.log("useEffect callback called");
// *** Added `if`
if (!showInputText && state >= 6) {
console.log("Setting timer");
// *** Moved
setTimeout(() => {
// You'll only see this one when `showInputText` was falsy when
// the `useEffect` callback was called just after rendering
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
}
}, [showInputText, state]);
Live Пример:
const { useState, useEffect } = React;
const classes = {
InputText: {
color: "green"
}
};
const Chat = () => {
const [state, setState] = useState(0);
const [showInputText, setShowInputText] = useState(false)
const typistCursor = {
hideWhenDone: true,
hideWhenDoneDelay: 200,
}
// *** Replaced Typist here just for demo purposes
const inputText = (<div>test@mail.com</div>)
// *** `useEffect` depending on `state` and `showInputText`
useEffect(() => {
// You'll see this console log every time the component is rendered
// with an updated `showInputText` or `state`
console.log("useEffect callback called");
// *** Added `if`
if (!showInputText && state >= 6) {
console.log("Setting timer");
// *** Moved
setTimeout(() => {
// You'll only see this one when `showInputText` was falsy when
// the `useEffect` callback was called just after rendering
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
}
}, [showInputText, state]);
return (
<div className={classes.EmailInput}>
{showInputText ? (inputText) : (<div className={classes.InputText}>Indtast din email her...</div>)}
<input type="button" onClick={
/* Just a really quick and dirty button to let us increment `state` */
() => setState(s => s + 1)
} value={`State: ${state} - Increment`} />
</div>
)
}
ReactDOM.render(<Chat />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
Наконец, если ваш компонент может быть перерисован по какой-то другой причине, чем вызов setShowInputText(true)
выше, вы можете захотеть отмените таймер, чтобы избежать устаревших вызовов, с помощью функции очистки в useEffect
hook:
// *** `useEffect` depending on `state` and `showInputText`
useEffect(() => {
// You'll see this console log every time the component is rendered
// with an updated `showInputText` or `state`
console.log("useEffect callback called");
// *** Added `if`
if (!showInputText && state >= 6) {
console.log("Setting timer");
// *** Moved
const timer = setTimeout(() => {
// You'll only see this one when `showInputText` was falsy when
// the `useEffect` callback was called just after rendering
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
// *** This is the cleanup function. It's a no-op if the timer has
// already fired; if the timer hasn't fired, it prevents it firing
// twice.
return () => clearTimeout(timer);
}
}, [showInputText, state]);
Live Пример:
const { useState, useEffect } = React;
const classes = {
InputText: {
color: "green"
}
};
const Chat = () => {
const [state, setState] = useState(0);
const [showInputText, setShowInputText] = useState(false)
const typistCursor = {
hideWhenDone: true,
hideWhenDoneDelay: 200,
}
// *** Replaced Typist here just for demo purposes
const inputText = (<div>test@mail.com</div>)
// *** `useEffect` depending on `state` and `showInputText`
useEffect(() => {
// You'll see this console log every time the component is rendered
// with an updated `showInputText` or `state`
console.log("useEffect callback called");
// *** Added `if`
if (!showInputText && state >= 6) {
// *** Moved
console.log("Setting timer");
const timer = setTimeout(() => {
// You'll only see this one when `showInputText` was falsy when
// the `useEffect` callback was called just after rendering
console.log('executing timeout');
setShowInputText(true);
}, 1000)
// ***
// *** This is the cleanup function. It's a no-op if the timer has
// already fired; if the timer hasn't fired, it prevents it firing
// twice.
return () => {
console.log("Clearing timer");
clearTimeout(timer);
};
}
}, [showInputText, state]);
return (
<div className={classes.EmailInput}>
{showInputText ? (inputText) : (<div className={classes.InputText}>Indtast din email her...</div>)}
<input type="button" onClick={
/* Just a really quick and dirty button to let us increment `state` */
() => setState(s => s + 1)
} value={`State: ${state} - Increment`} />
</div>
)
}
ReactDOM.render(<Chat />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>