Как передать состояние успеха обратно в компонент без обновления хранилища - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть простая форма в response-redux, предназначенная для попытки добавить пользователя в базу данных, если она прошла успешно, отобразить сообщение об успехе.Однако я не уверен в лучшем подходе для этого.У меня есть следующее:

onSubmit = e => {
  ...
  const newUser = { user object here }
  this.props.registerUser(newUser);
}

в componentWillReceiveProps(nextProps):

if (nextProps.success === true) {
    this.setState({ success: nextProps.success });
}

в render(): Предназначено для отображения компонента успеха с дополнительной информацией.Существует также условная проверка, чтобы скрыть форму, если успех равен true

{ this.state.success === true && 
  (<SuccessComponent name={this.state.name} />)
}

в mapStateToProps:

const mapStateToProps = state => ({
  success: state.success
});

в моем action:

.then(res => {
  dispatch({
    type: REGISTRATION_SUCCESS,
    payload: true
  });
})

в reducer:

const initialState = false;

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

в combineReducers:

export default combineReducers({
  success: successReducer
});

В этом я в основном использую ответ от сервера для отправки успехаподдержать компонент, обновить состояние, которое заставляет реагировать на рендеринг, и снова пройти через условный оператор, скрывая форму и отображая новый блок успеха.

Тем не менее, когда я вхожу в инструменты для создания избыточного кода, я вижу, что состояние из хранилища теперь true и остается таким, если пользователи уходят.Есть ли лучший способ достичь этой цели?Я нахожу, что, возможно, это должно быть изолировано для самого состояния компонента, но я не уверен, как это сделать, так как действие и, следовательно, ответ сервера происходит через избыточный код.

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Прежде всего, я не думаю, что вы должны использовать свой магазин Redux для сохранения того, что по сути является локальным состоянием.

Если бы это был я, я, вероятно, попытался бы сделать вызов API непосредственно из компонента, а затем записать его в хранилище избыточных данных, если оно прошло успешно.Таким образом, вы можете избежать получения своего производного состояния в компоненте.

Тем не менее, если вы хотите сделать это таким образом, я бы предложил componentWillUnmount.Это позволило бы вам сделать еще один вызов Redux, который вернул бы ваше логическое значение регистрации к значению false, когда вы покинете страницу.

0 голосов
/ 06 февраля 2019

Redux - это конечный автомат, а не шина сообщений, поэтому постарайтесь, чтобы значения состояния представляли текущее состояние приложения, а не отправляли одноразовые сообщения.Те могут по возвращаемому значению создателя действия.Успех или неудача могут быть просто наличием / отсутствием ошибки создателя действия.

Если вы действительно хотите сохранить информацию о пользователе, вы можете получить свое состояние «успешно» благодаря зарегистрированномупользователя, и удалите любого существующего зарегистрированного пользователя при монтировании компонента.

// actions.js
export const clearRegisteredUser = () => ({
  type: SET_REGISTERED_USER,
  payload: null,
})

export const register = (userData) => async (dispatch) => {
  // async functions implicitly return a promise, but
  // you could return it at the end if you use the .then syntax
  const registeredUser = await api.registerUser(userData)
  dispatch({
    type: SET_REGISTERED_USER,
    payload: registeredUser,
  })
}

// reducer.js
const initialState = { registeredUser: null }
const reducer = (state = initialState, { type, payload }) => {
  switch(type) {
    case SET_REGISTERED_USER: {
      return {
        ...state,
        registeredUser: payload,
      }
    }
    default: {
      return state
    }
  }
}

// TestComponent.js
class ExampleComponent extends Component {
  state = {
    registrationError: null,
  }

  componentWillMount() {
    this.props.clearRegistered()
  }

  handleSubmit = async (formData) => {
    try {
      this.props.register(formData)
    } catch(error) {
      // doesn't really change application state, only
      // temporary form state, so local state is fine
      this.setState({ registrationError: error.message })
    }
  }

  render() {
    const { registrationError } = this.state
    const { registeredUser } = this.props

    if (registrationError) {
      return <FancyError>{registrationError}</FancyError>
    } else if (registeredUser) {
      return <SuccessComponent name={this.props.registeredUser.name} />
    } else {
      return <UserForm onSubmit={this.handleSubmit} />
    }
  }
}

Если вам действительно не нужна информация о пользователе после регистрации, вы можете просто выполнить вызов API напрямую и оставить Redux вне его..

class ExampleComponent extends Component {
  state = {
    registered: false,
    registrationError: null,
  }

  handleSubmit = async (formData) => {
    try {
      await api.registerUser(formData)
      this.setState({ registered: true })
    } catch(error) {
      this.setState({ registrationError: error.message })
    }
  }

  render() {
    const { registered, registrationError } = this.state

    if (registrationError) {
      return <FancyError>{registrationError}</FancyError>
    } else if (registered) {
      return <SuccessComponent name={this.props.registeredUser.name} />
    } else {
      return <UserForm onSubmit={this.handleSubmit} />
    }
  }
}

Наконец, по возможности, избегайте сохранять копии избыточного состояния в состоянии вашего компонента.Это может легко привести к проблемам синхронизации.Вот хорошая статья о том, как избежать производного состояния: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

...