如何在React Hooks中使用setTimeout更新状态值?

时间:2019-09-09 13:27:38

标签: javascript reactjs redux react-hooks

我正在尝试使用setTimeout函数在一段时间后重置状态值。

const SetTimeout = props => {
  let [errorText, setError] = useState(
    props.errorMessage ? props.errorMessage : ""
  );
  useEffect(() => {
    if (errorText !== "") {
      setTimeout(() => {
        setError("");
      }, 4000);
    } else {
      // console.log("no error")
    }
  }, [errorText]);
  return <div>{errorText}</div>;
};

const MapStateToProps = state => {
  return {
    errorMessage: state.errorReducer.error
  };
};

我正在从api调用中获取errorMessage,一段时间之后,我正尝试使用useState将该消息清空。

但是该组件正在使用相同的错误消息重新呈现。您能帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:2)

您在这里混合了组件状态和redux状态,这很糟糕,为什么您会看到这种行为。

您最初是在Redux内部使用错误消息来呈现组件,并将其作为属性值传递到组件中。组件显示此内容,设置其自身的状态值。超时运行后,它将更新其自身的状态,这将导致重新渲染,然后Redux值会再次通过属性传递到组件中。

我建议您忘记使用useState并使用Redux操作清除存储的错误消息。

答案 1 :(得分:1)

您正在使用redux在React组件中不使用状态,而在这里您正在组件中使用状态。因此,您可以做的就是将erromessage添加到全局状态:

state ={
...,
errormessage:undefined
}

,然后在操作中需要像这样更改state.errormessage

export const show_error = message => {
    return {
        type: "SHOW_ERROR",
        payload: message
    };
};
export const remove_error = () => {
    return {
        type:"REMOVE_ERROR"
    };
};

想象调用post api以使用redux thunk添加帖子,您可以这样做:

export function add_post(data) {
    return function(dispatch) {
        return axios
            .post('/posts', data)
            .then(res => {
                dispatch(fetch_posts_data());})
            .catch(err =>  dispatch(
                    show_error(err)
                );
                setTimeout(function() {
                    dispatch(remove_error());
                }, 2000););
    };
}

在减速器中:

 case "SHOW_ERROR":
            return {
                ...state,
                posts: { ...state.posts, errormessage: action.message}
            };
        case "REMOVE_ERROR":
            return {
                ...state,
                posts: { ...state.posts, errormessage: undefined }
            };

现在要检索组件中的errormessage,您可以使用常规的connect方法,但是在这里,我将使用Redux钩子useSelector()

const Error = ()=>{
 const errormessage = useSelector(state=>state.errormessage)
     return(
    <>
     {

    errormessage?
    <div>{errormessage}</div>
    :""

    }
    </>
       )
        }

答案 2 :(得分:0)

我刚刚发现了这个!因此,它可能并不完美。

挂钩具有useSelectoruseDispatch(来自react-redux

要坚持在Redux中出错,您的组件应如下所示:

const SetTimeout = () => {
    const errorText = useSelector(state => state.errorReducer.error);
    const clearError = useDispatch();

    useEffect(() => {
        if (errorText !== "") {
            const timeout = setTimeout(() => {
                clearError({ type: "CLEAR_ERROR" });
            }, 5000);
        } else {
            // console.log("no error")
        }
        // this will clear Timeout when component unmounts like in willComponentUnmount
        return () => { clearTimeout(timeout); };
    }, []);

    return <div style={{ color: "red" }}>{errorText}</div>;
};

export default SetTimeout;

非常酷的功能组件,没有redux样板代码。

希望有帮助