change to new value of state using mapDispatchToProps

僤鯓⒐⒋嵵緔 提交于 2020-02-04 03:35:20

问题


Profile.js

The Profile screen fetches its data from the WebApi using redux and displayes the Image according to the imageUrl. The SelectImage() calls a function for users to open up the gallery and choose a new image.

After choosing the Image, I would like the image to be shown on the screen and replace current value of this.props.items.imageUrl. I just started redux and implemented it to my application. I would like to update the state of redux and be accessed on other screens as well, as the picture will be shown in other screens as well. However, I am unable to change the Image inside the app.

All the data is inside items

          <TouchableOpacity
            onPress={() => this.selectImage()}>
            <View style={styles.piccontainer}>
              <Image
                source={{ uri: this.props.items.imageUrl }}
                style={styles.photo} />
            </View>
          </TouchableOpacity>
          <TouchableOpacity style={styles.button}
              onPress={() => {
                this.uploadImage();
                this.goBack()
              }}>
              <View>
                <Text style={styles.text}>Save</Text>
              </View>
          </TouchableOpacity>

This is my selectImage() function

  selectImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1
    });
    let file = result.uri
    if (!result.cancelled) {
      this.updatePicture(file)
    }
  }

I believe that i have to mapDispatchToProps to call an action.

function mapDispatchToProps(dispatch) {
  return {
    updatePicture: file => {dispatch(updatePicture(file))}
  }
}

I'm lost after calling the function, do I put the reducers and actions in the same place as I put the function that fetches profile data? Do i create a new file, but if i do so, what do i set the initial state as? Thank you for the help. I appreciate it alot.

profileReducer.js

const initialState = {
  profilepic: '',
};

export default function updateprofileReducer(state = initialState, action) {
  switch (action.type) {
    case UPDATE_PICTURE:
      return {
        ...state,
        profilepic: action.payload.file
      }
    default:
      return state;
  }
}

profileAction.js

export const updatePicture = file => ({
    type: UPDATE_PICTURE,
    payload: file
})

回答1:


I think there is a typo in the reducer:

    case UPDATE_PICTURE:
      return {
        ...state,
        profilepic: action.payload, // <--- this instead of action.payload.file 
      }

and since you didn't mention, you will need to mapStateToProps to map your profilepic state in redux to your prop.

but here bring up another issue, your props is in the format of object (items.imageUrl). but your state is just a string (profilepic). Unless you mean to make a profilepic an object which store an items of profilepic images which your reducer is not doing that, you will need to fix that. Or otherwise, if you mean to store only one image url at a time, you need to map the redux state to a new prop and set the init value to be your items.imageUrl value.

EDIT: base on what OP clarified, here is some more sample code, note: since i don't have the whole piece of code so I don't know is there any helper method to inject the new reducer to the store and set the init value. that's prefer method but just for showing the idea of mapStateToProps:

<TouchableOpacity onPress={() => this.selectImage()}>
  <View style={styles.piccontainer}>
    <Image
      source={{ uri: this.props.imageUrlFromRedux || this.props.items.imageUrl }}
      style={styles.photo}
    />
  </View>
</TouchableOpacity>

and then you have define the mapStateToProps

const mapStateToProps = state => ({
  imageUrlFromRedux: state.profilepic,
});

export default connect(mapStateToProps, mapDispatchToProps)(YourComponent);

hope this help. and please remember to fix your reducer




回答2:


You should add some changes

profileAction.js

export const profileAction = file => ({
    type: UPDATE_PICTURE,
    payload: file
})

profileReducer.js

import {profileAction} from 'profileAction.js';

export function updatePicture (file) {
    return (dispatch)=> {
        //some action with file
        dispatch(profileAction(file)); 
    };
}

export default function updateprofileReducer(state = initialState, action) {
  switch (action.type) {
    case UPDATE_PICTURE:
      return {
        ...state,
        profilepic: action.payload.file
      }
    default:
      return state;
  }
}

then import updatePicture in your react file, connect with your react class like this

export default connect(mapStateToProps, mapDispatchToProps)(YourComponent);

Replace mapDispatchToprops like this

function mapDispatchToProps(dispatch) {
  return {
    updatePicture: file => dispatch(updatePicture(file))
  }
}

You have mistake in your selectImage function. You should replace this code fragment like this

 if(!result.cancelled) {
      this.props.updatePicture(file);
  }

Your updatePicture function is available only from props.



来源:https://stackoverflow.com/questions/59901275/change-to-new-value-of-state-using-mapdispatchtoprops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!