从其他组件设置状态

时间:2019-04-23 17:57:14

标签: javascript reactjs react-hooks

首先,我的方法可能从一开始就被误导。

我有一个列出同级组件添加的对象的组件。

我希望在添加新对象时更新列表组件。

如您所见,我在两个组件中都调用了相同的函数(getHostedServiceList)。显然,这不需要清理,但我想先使其工作

我正在使用钩子来完成此操作。

//输入

const options = [
  { value: '1', label: '1' },
  { value: '2', label: '2' },
  { value: '3', label: '3' },
];

// class Remotes extends Component {
const Remotes = ({ ...props }) => {
  const [service, setService] = useState();
  const [url, setUrl] = useState();
  const [token, setToken] = useState();
  const [displayName, setDisplayName] = useState();
  const [apiUrl, setApiUrl] = useState();
  const [services, setServices] = useState();

  let HOME = process.env.HOME || '';
  if (process.platform === 'win32') {
    HOME = process.env.USERPROFILE || '';
  }

  const getHostedServiceList = () => {
    console.log('props', props);
    if (!fs.existsSync(`${HOME}/providers.json`)) {
      return newMessage(
        `Unable to locate ${HOME}/providers.json`,
        'error',
      );
    }
    const payload = JSON.parse(
      fs.readFileSync(`${HOME}/providers.json`),
    );

    setServices(payload);
  };

  const setProvider = selectedOption => {
    setService(selectedOption.value);
    setUrl(`http://www.${selectedOption.value}.com`);
    setApiUrl(`http://www.${selectedOption.value}.com/api/v1`);
  };

  const { onAddRemote } = props;
  return (
    <div>
      <div>Add a remote host:</div>
      <StyledSelect
        value="Select Provider"
        onChange={setProvider}
        options={options}
      />
      {console.log('service', service)}
      <TextInput
        label="Url"
        defaultValue={url}
        onChange={e => {
          setProvider(e.target.value);
        }}
        disabled={!service ? 'disabled' : ''}
      />

      <TextInput
        label="API Url"
        defaultValue={apiUrl}
        onChange={e => setApiUrl(e.target.value)}
        disabled={!service ? 'disabled' : ''}
      />

      <TextInput
        label="Token"
        onChange={e => setToken(e.target.value)}
        disabled={!service ? 'disabled' : ''}
      />

      <TextInput
        label="Display Name"
        onChange={e => setDisplayName(e.target.value)}
        disabled={!service ? 'disabled' : ''}
      />

      <Button
        disabled={!service || !url || !token}
        onClick={() => {
          onAddRemote({ service, url, apiUrl, token, displayName });
          getHostedServiceList();
        }}
      >
        Add Remote
      </Button>
    </div>
  );
};

//列表


const HostedProviderList = ({ ...props }) => {
  const [services, setServices] = useState();

  let HOME = process.env.HOME || '';
  if (process.platform === 'win32') {
    HOME = process.env.USERPROFILE || '';
  }

  const getHostedServiceList = () => {
    console.log('props', props);
    if (!fs.existsSync(`${HOME}/providers.json`)) {
      return newMessage(
        `Unable to locate ${HOME}/providers.json`,
        'error',
      );
    }
    const payload = JSON.parse(
      fs.readFileSync(`${HOME}/providers.json`),
    );

    setServices(payload);
  };

  useEffect(() => {
    // console.log('props 1', services);
    getHostedServiceList();
  }, []);

  return (
    <Wrapper>
      <Flexbox>
        <Title>Provider List</Title>
      </Flexbox>
      <div>
        {services &&
          services.map((service, i) => (
            <Service key={i}>
              <ServiceName>{service.displayName}</ServiceName>
              <ServiceProvider>{service.service}</ServiceProvider>
            </Service>
          ))}
      </div>
    </Wrapper>
  );
};

我希望在添加新对象时更新列表组件。

2 个答案:

答案 0 :(得分:0)

在这里方便使用ReduxMobX之类的东西。这些工具可让您创建一个“商店”-加载和存储整个应用程序中不同组件使用的数据的 数据的位置。然后,您将商店连接到与数据交互的各个组件(显示列表,显示创建/编辑表单等)。只要一个组件修改了数据,其他所有组件都会自动接收更新。

实现这种交叉通信的一种方式是通过pub/sub机制-每当一个组件创建或修改数据时,它就会发布(或“分发”)一个事件。其他组件 subscribe (或“监听”)这些事件,并反应(或“重新渲染”)。我将把研究和实现留给读者,因为它不能在StackOverflow答案中快速总结。

您还可以尝试新的React hooks,因为这使您可以轻松地在组件之间共享数据。如果选择此选项,请特别小心以使其正确执行,因为它容易变得懒惰且不负责任。

为使您入门,请阅读以下文章。我强烈建议您阅读第一个:

答案 1 :(得分:0)

是的,您可以使用Redux(或React自己的“上下文”)进行全局状态处理。但是,要考虑的一个更简单的解决方案可能是将数据发送给父级并传递给列表组件,如下所示:

class Parent extends Component {
  state = { objectsAdded: [] }

  onObjectAdded = ( obj ) => {
    // deepclone may be needed
    this.setState({objectsAdded: this.state.objectsAdded.concat(obj)})
  }

  render() {
    return (
      <Fragment>
        <ListComponent objects={this.state.objectsAdded} />
        <ObjectAdder onObjectAdded={this.onObjectAdded} />
      </Fragment>
  }
}