У меня есть компонент React, а внутри метода render компонента у меня есть что-то вроде этого:

render() {
    return (
        
// removed for brevity
{ switch(...) {} }
// removed for brevity
); }

Now the point is that I have two div elements, one at the top and one at the bottom, that are fixed. In the middle I want to have a switch statement, and according to a value in my state I want to render a different component. So basically, I want the two div elements to be fixed always, and just in the middle to render a different component each time. I'm using this to implement a multi-step payment procedure). Though, as is the code currently it doesn't work, as it gives me an error saying that switch is unexpected. Any ideas how to achieve what I want?

typos

Ответов: 21

Ответы (21)

Попробуйте это, что тоже намного чище: выньте этот переключатель из рендеринга в функции и просто вызовите его, передав нужные вам параметры. Например:

renderSwitch(param) {
  switch(param) {
    case 'foo':
      return 'bar';
    default:
      return 'foo';
  }
}

render() {
  return (
    
// removed for brevity
{this.renderSwitch(param)}
// removed for brevity
); }

Можно сделать что-то вроде этого.

 
{ object.map((item, index) => this.getComponent(item, index)) }
getComponent(item, index) { switch (item.type) { case '1': return case '2': return case '3': return } }

Способ представления своего рода переключателя в блоке рендеринга с использованием условных операторов:

{(someVar === 1 &&
    )
|| (someVar === 2 &&
    )
|| (this.props.someProp === "something" &&
    )
|| (this.props.someProp === "foo" && this.props.someOtherProp === "bar" &&
    )
||
    
}

Следует убедиться, что условия строго возвращают логическое значение.

ответ ленкана - отличное решение.

{{ beep:
Beep
, boop:
Boop
}[greeting]}

Если нужно значение по умолчанию, то можно даже

{{ beep:
Beep
, boop:
Boop
}[greeting] ||
Hello world
}

В качестве альтернативы, если вам это не нравится, вы можете сделать что-нибудь вроде

{ rswitch(greeting, { beep:
Beep
, boop:
Boop
, default:
Hello world
}) }

с

function rswitch (param, cases) {
  if (cases[param]) {
    return cases[param]
  } else {
    return cases.default
  }
}

Я не большой поклонник текущих ответов, потому что они либо слишком подробны, либо требуют от вас беготни по коду, чтобы понять, что происходит.

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

Пример:

const Switch = props => {
  const {test, children} = реквизит
  // отфильтровываем только детей с подходящей опорой
  return children.find (child => {
    вернуть child.props.value === test
  })
}

const Sample = props => {
  const someTest = истина
  возвращение (
    
      
Будет отображаться, если someTest имеет значение false
Будет отображаться, если someTest истинно
) } ReactDOM.render ( <Образец />, document.getElementById ("реагировать") );


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

Я преобразовал принятый ответ в решение функционального компонента стрелки и увидел, что Джеймс дает аналогичный ответ, и можно получить ошибку не определено. Итак, вот решение:

  const renderSwitch = (param) => {
    switch (param) {
      case "foo":
        return "bar";
      default:
        return "foo";
    }
  };

  return (
    
{renderSwitch(param)}
);

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

вы можете установить конструктор следующим образом

constructor(props)
{
    super(props);
    this.state={
        currentView: ''
    }
}

, тогда вы можете визуализировать компоненты следующим образом

  render() 
{
    const switchView = () => {

    switch(this.state.currentView) 
    {

      case "settings":   return 

settings

; case "dashboard": return

dashboard

; default: return

dashboard

} } return (
{ switchView() }
); }

}

Как видите, я использую кнопку для переключения между состояниями.

Я знаю, что немного опаздываю на вечеринку, но думаю, что эта реализация может помочь

Вместо этого вы можете визуализировать компоненты, используя условные операторы

Если бы у вас был следующий оператор switch

switch(value) {
    case CASE1:
        return 

    case CASE2:
        return 

    case CASE3:
        return 

    default:
        return 
}

Вы можете преобразовать его в реагирующий компонент, например,

const cases = [CASE0, CASE1, CASE2]
// Reminds me of 'react-router-dom'
return (
    
{value === cases[0] && } {value === cases[1] && } {value === cases[2] && } {!cases.includes(value) && }
)

Although this is yet another way to do it, if you have gone all-in on hooks, you could take advantage of useCallback to produce a function that is only recreated when necessary.

Допустим, у вас есть компонент, который должен отображаться в соответствии со свойством status. С помощью хуков вы можете реализовать это следующим образом:

const MyComponent = ({ status }) => {
  const renderContent = React.useCallback(() => {
    switch(status) {
      case 'CONNECTING': 
        return 

Connecting...

; case 'CONNECTED': return

Connected Successfully!

default: return null; } }, [status]); return (
{renderContent()}
); };

Мне это нравится, потому что:

  • Очевидно, что происходит - функция создается, а затем вызывается (немедленно вызванный метод анонимной функции выглядит немного странно и потенциально может сбить с толку новых разработчиков)
  • Ловушка useCallback гарантирует, что обратный вызов renderContent повторно используется между отрисовками, если только зависимость status не изменится
  • Функция renderContent использует закрытие для доступа к необходимым пропсам, переданным в компонент. Отдельная функция (например, принятый ответ) требует передачи в нее реквизита, что может быть обременительным (особенно при использовании TypeScript, поскольку параметры также должны быть введены правильно)

Мне очень понравилось предложение в https://stackoverflow.com/a/60313570/770134, поэтому я адаптировал его к Typescript вот так

import React, { FunctionComponent } from 'react'
import { Optional } from "typescript-optional";
const { ofNullable } = Optional

interface SwitchProps {
  test: string
  defaultComponent: JSX.Element
}

export const Switch: FunctionComponent = (props) => {
  return ofNullable(props.children)
    .map((children) => {
      return ofNullable((children as JSX.Element[]).find((child) => child.props['value'] === props.test))
        .orElse(props.defaultComponent)
    })
    .orElseThrow(() => new Error('Children are required for a switch component'))
}

const Foo = ({ value = "foo" }) => 
foo
; const Bar = ({ value = "bar" }) =>
bar
; const value = "foo"; const SwitchExample = }> ;

Это другой подход.

render() {
   return {this[`renderStep${this.state.step}`]()}

renderStep0() { return 'step 0' }
renderStep1() { return 'step 1' }

упростите задачу и просто используйте множество операторов if.

например:


   {yourVar==="val1"&&(<> your code for val1 )}
   {yourVar==="val2"&&(<> your code for val2 )}
   .... other statments

import React from 'react';

import ListView from './ListView';
import TableView from './TableView';

function DataView({
    currView,
    data,
    onSelect,
    onChangeStatus,
    viewTodo,
    editTodo,
    deleteTodo,
}) {
    return (
        
{(function () { switch (currView) { case 'table': return ( ); case 'list': return ( ); default: break; } })()}
); } export default DataView;

function Notification({ text, status }) {
  return (
    
{(() => { switch (status) { case 'info': return ; case 'warning': return ; case 'error': return ; default: return null; } })()}
); }

Как насчет:

mySwitchFunction = (param) => {
   switch (param) {
      case 'A':
         return ([
            
, ]); // etc... } } render() { return (
// removed for brevity
{ this.mySwitchFunction(param) }
// removed for brevity
); }

Оператор Switch-Case в компоненте React может использоваться следующим образом:

{ (() => { switch (groupByFilterId) { case 0:/*Case 0 */ return (
Case 0
) break; case 1: /*Case 1 */ return (
Case 1
) break; case 2:/*Case 2 */ return (
Case 2
) break; } })()}

Я сделал это внутри метода render ():

  render() {
    const project = () => {
      switch(this.projectName) {

        case "one":   return ;
        case "two":   return ;
        case "three": return ;
        case "four":  return ;

        default:      return 

No project match

} } return (
{ project() }
) }

Я пытался сохранить в чистоте возврат render (), поэтому я поместил свою логику в функцию 'const' прямо выше. Таким образом я могу аккуратно сделать отступы на корпусах переключателей.

Это происходит, потому что оператор switch является оператором , но здесь javascript ожидает выражения.

Хотя не рекомендуется использовать оператор switch в методе render, для этого можно использовать самозапускающуюся функцию:

render() {
    // Don't forget to return a value in a switch statement
    return (
        
{(() => { switch(...) {} })()}
); }

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

Вот хороший чистый способ сделать это, не требующий предварительного рендеринга каждого вида:

render () {
  const viewState = this.getViewState();

  return (
    
{viewState === ViewState.NO_RESULTS && this.renderNoResults()} {viewState === ViewState.LIST_RESULTS && this.renderResults()} {viewState === ViewState.SUCCESS_DONE && this.renderCompleted()}
)

Если ваши условия, для которых состояние просмотра основано на более чем простом свойстве, например, несколько условий на строку, то перечисление и getViewState функция для инкапсуляции условий - хороший способ разделить это условное логика и очистка вашего рендера.

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

render () {
  return (
    
{/* removed for brevity */}
{ { 'foo': , 'bar': }[param] }
{/* removed for brevity */}
) }

Этот ответ специально предназначен для ответа на этот «повторяющийся» вопросот @tonyfat, касающийся использования условных выражений для обработки той же задачи.


// Запускает тесты
пусть id = 0, flag = 0;
renderByFlag (идентификатор, флаг); // jobId вне допустимого диапазона

id = 1; // jobId в диапазоне
while (++ flag <5) {// активный флаг варьируется от 1 до 4
  renderByFlag (идентификатор, флаг);
}

// Определяет функцию, которая выбирает, что отображать, на основе двух предоставленных значений
function renderByFlag (jobId, activeFlag) {
  jobId === 1? (
      activeFlag === 1
        ? render ("A (flag = 1)")
        : activeFlag === 2
          ? render ("B (flag = 2)")
          : activeFlag === 3
            ? render ("C (flag = 3)")
            : pass (`флаг $ {activeFlag} вне допустимого диапазона`)
  )
  : pass (`jobId $ {jobId} вне допустимого диапазона`)
}

// Определяет функции регистрации для демонстрационных целей
функция render (val) {console.log (`Отрисовка $ {val}`); }
функция pass (причина) {console.log (`Ничего не делая ($ {причина})`)}

2022 WebDevInsider