FileReader-存储更新后如何更新本地状态?

时间:2020-09-18 00:59:43

标签: reactjs redux filereader

我正在玩一个食物识别API。

我有一个本地状态为ingredients的组件。

在组件中,我有一个input标记,该标记接受文件图像上载并调用cameraHandler方法onChange。该方法使用FileReader将图像转换为Base64

一旦FileReader完成对图像的编码,该方法将调用redux操作fetchIngredientsFromImage,将base64图像发布到路由中,以触发以触发API调用(以分析图像中的成分)。

响应被发送回前端,并用于更新存储。

因此,基本上,API调用成功,我获得了所需的数据,并且存储成功更新。很好。

但是我还需要做的是更新本地ingredients状态。但是我不知道如何在调用setState之前等待商店更新。

我已经尝试过使用if(this.props !== prevProps) methodToUpdateLocalState()来componentDidUpdate,但是这不起作用,因为由于某种原因,存储更新后组件将不会重新呈现。.结果是componentDidUpdate内部的所有内容都首先运行并存储之后进行更新。我觉得(也可能)也没有必要。

我还尝试了.then cameraHandler中等待的读者,但是.then是未定义的。

我将不胜感激。在这里真的很茫然,因为我有数据,我只需要以某种方式获取它,这样我就可以设置状态。

组件

class RecipesSearch extends Component {
  state = {
    ingredients: [], //need to update this after store is updated, but how?
  };

  cameraHandler = async (event) => {
    const { fetchIngredientsFromImage } = this.props;
    const file = event.target.files[0];
    const reader = new FileReader();
    await reader.readAsDataURL(file);
    reader.onloadend = async () => {
      const imgBase = reader.result.replace(/^data:image\/(.*);base64,/, '');
      await fetchIngredientsFromImage(imgBase); //.then here is undefined
    };
  };

render(){
  <input
    className="form-check-input"
    type="file"
    name="camera"
    accept="image/*"
    onChange={this.cameraHandler}
  />
}

操作

const fetchIngredientsFromImage = (imgBase) => async (dispatch) => {
  const { data } = await axios.post(`/api/camera/`, { imgBase });
  return dispatch(setIngredientsFromCamera(data)); //successfully updates store
};

1 个答案:

答案 0 :(得分:0)

作为一种解决方法,我在cameraHandler内进行了axios.post调用。不为它感到骄傲,因为我想利用存储并使它与其他方法保持一致,但是暂时我会猜到。

cameraHandler = async (event) => {
    // const { loadIngredientsFromImage } = this.props;
    const file = event.target.files[0];
    const reader = new FileReader();
    await reader.readAsDataURL(file);
    reader.onloadend = async () => {
      const imgBase = reader.result.replace(/^data:image\/(.*);base64,/, '');
      await axios
        .post(`/api/camera/`, { imgBase })
        .then((response) => this.setState({ ingredients: response.data }));
    };
  };