Shadowman
Shadowman

Reputation: 285

Redux state doesn't update from the first time

Maybe that's a stupid question, but I have a problem. My state looks like this:

const initialState: PhotoState = {
  photos: [],
};

The reducer code looks like this:

const initialState: PhotoState = {
  photos: [],
};

export default function photoReducer(state = initialState, action: PhotoActionTypes): PhotoState {
  switch (action.type) {
    case SET_PHOTOS:
      const photos: any[] = action.payload;
      return {...state, photos};
  }

  return state;
};

I get photos from API and then set them this way:

export function setPhotos(payload: any[]): PhotoActionTypes {
  return {type: SET_PHOTOS, payload};
}

export function getPhotos() {
  return (dispatch: Dispatch<PhotoActionTypes>, getState: () => RootState): void => {
    const profile_id = getState().auth.profile_id;
    ax().post('pictures/api/pictures/list', {profile_id}).then((response) => {
      const photos: any[] = response.data.pictures || [];
      dispatch(setPhotos(photos));
    })
  }
}

Also I have an action that sends a new photo to the server and saves it in history. Then I get photos in component:

useEffect(() => {
    dispatch(getPhotos());
  }, []);

const handleSendPhoto = (): void => {
    dispatch(sendPhoto(image?.base64));
    dispatch(getPhotos());
  }

The whole component:

const PhotoScreen = () => {
  const [photoFlag, setPhotoFlag] = useState(false);
  const [image, setImage] = useState<TakePictureResponse | null>(null);
  const [height, setHeight] = useState(0);
  const width = Dimensions.get('screen').width / 5;
  const dispatch = useDispatch();

  const handleSendPhoto = (): void => {
    dispatch(sendPhoto(image?.base64, location));
    dispatch(getPhotos());
  }

  const PhotoView = () => (
    <View>
      <FastImage
        style={{width: width, height: height}}
        source={{
          uri: `data:image/jpeg;base64, ${image?.base64}`,
          priority: FastImage.priority.normal,
        }}
        resizeMode={FastImage.resizeMode.contain}
        onLoad={evt => {
          setHeight(evt.nativeEvent.height / evt.nativeEvent.width * width)
        }}
      />
      <Button
        mode="contained"
        onPress={handleSendPhoto}
        disabled={!image}
        color={constants.buttonColor}>
        Add photo
      </Button>
    </View>
  );

  return (
    <SafeAreaView style={{...mainStyles.screen, ...styles.container}}>
      <StatusBarDark />
      {!photoFlag && (<View>
        <Button
          mode="contained"
          onPress={() => setPhotoFlag(true)}
          color={constants.buttonColor}>
          Make photo
        </Button>
      </View>)}

      {photoFlag && <CameraComponent setImage={setImage} setPhotoFlag={setPhotoFlag}/>}
      {image !== null && <PhotoView />}
    </SafeAreaView>
  );
};

export default PhotoScreen;

But state updates only from the second time. I press the button 'Add photo', photo appends to history, but doesn't shows up in it. Then I press the button again, and previous photo shows up in history, but current photo doesn't.

How can I fix it?

UPD: Problem was solved. The question may be closed.

Upvotes: 0

Views: 314

Answers (1)

TheWuif
TheWuif

Reputation: 1036

You shouldn't do this, because both calls will be send at the same time:

const handleSendPhoto = (): void => {
  dispatch(sendPhoto(image?.base64));
  dispatch(getPhotos()); // this will be called before the upload is finished. so the old data will be returned.
}

you may need to use redux-thrunk (https://github.com/reduxjs/redux-thunk) like this:

const handleSendPhoto = (): void => {
  dispatch(sendPhoto(image?.base64)).then(() => dispatch(getPhotos()));
}

Upvotes: 2

Related Questions